此过程是此目标应用程序中最常访问的过程。假设并发操作,并且t.value总是在变化。
-- Table is MySQL InnoDB
-- let's call this MainSelect
SELECT t.Id
FROM table t
WHERE t.A = conditionA AND t.B = conditionB AND t.value > 0
ORDER BY RAND()
LIMIT 1 INTO vIndex FOR UPDATE;
-- IF vIndex THEN
UPDATE table SET value = value - 1 WHERE id = vIndex
目标是修改此查询以使用this method of random row selection形式的速度。这里是为了完整性。这是这篇文章的主要问题。
SELECT name
FROM random AS r1 JOIN
(SELECT (RAND() *
(SELECT MAX(id)
FROM random)) AS id)
AS r2
WHERE r1.id >= r2.id
ORDER BY r1.id ASC
LIMIT 1
讨论:
MainSelect中的总行数将如何确定?
如果答案是生成MainSelect子查询,将FOR UPDATE移动到最外层查询,则在外部SELECT使用FOR UPDATE锁定行之前,随机选择的行的t.value可能变为0。类似的东西:
SELECT * FROM (firstquery) s ...random selection logic.. FOR UPDATE;
如果这种考虑是准确的,那么就会在一开始就设置哪个交易级别的问题。
由于
修改 - 工作时注释:
也许http://en.wikipedia.org/wiki/Reservoir_sampling,因为计数未知。我希望避免高隔离级别,因为我预计会降低吞吐量。
也许可以存储和索引随机数,而不是计算。然后选择一个随机数,根据limit documentation,随机选择一个非常快。这个问题是结果集不一致。
如果将LIMIT row_count与ORDER BY一起使用,则MySQL将排序结束为 很快它找到了排序结果的第一个row_count行, 而不是整理整个结果。如果订购是通过使用 索引,这非常快。