有没有办法优化以下查询?
SELECT count(*)>1000 FROM table_with_lot_of_rows WHERE condition_on_index;
使用此查询,MySQL首先执行count(*)
然后进行比较。当只有少数几行满足条件时,这是快速的,但如果很多行满足它,则可以永久保存。有没有办法在找到1000个项目后立即停止计数,而不是通过所有结果?
特别是,我对具有全文条件的MyISAM表感兴趣,但对InnoDB和/或基本WHERE子句的任何答案都会有所帮助。
答案 0 :(得分:4)
SELECT 1
FROM table_with_lot_of_rows
WHERE condition_on_index
LIMIT 1000, 1;
以这种方式工作:
1
(在SELECT
中)。现在您要么为空结果集(< = 1000行),要么为1
行(至少1001行)。
然后,根据您的应用程序语言,很容易区分这两种情况。
另一个注意事项:如果这是一个更大的查询中的子查询,那么执行
EXISTS ( SELECT 1
FROM table_with_lot_of_rows
WHERE condition_on_index
LIMIT 1000, 1 )
返回TRUE / FALSE(与1或0同义)。
面对它,扫描1001行,甚至索引,将花费一些时间。我认为我的表述是最快的。
其他要检查的事项:这是InnoDB吗?请EXPLAIN
说"使用索引"?内存多少钱? innodb_buffer_pool_size
的设置是什么?
请注意,InnoDB现在有FULLTEXT,因此没有理由坚持使用MyISAM。
如果您使用的是MyISAM且WHERE
为MATCH...
,那么我所说的大部分内容可能都不适用。 FULLTEXT
可能取得所有结果,然后让其他引擎有机会使用ORDER BY
和LIMIT
进行这些游戏。
请向我们展示实际查询,EXPLAIN
和SHOW CREATE TABLE
。真正的目标是什么?要查看查询是否会传递太多"结果
可能的改进(取决于具体情况)
由于我的初始SELECT
返回标量1
或NULL
,因此可以在任何布尔上下文中使用它,例如WHERE
。 1
为TRUE
,NULL
将被视为FALSE
。因此EXISTS
可能是多余的。
此外,1
/ NULL
可以转换为1
/ 0
。注意:需要额外的parens。
IFNULL( ( SELECT ... LIMIT 1000,1 ), 0)
答案 1 :(得分:1)
您可以使用LIMIT:
的子查询来优化查询SELECT count(*)>1000 FROM (
SELECT 0 table_with_lot_of_rows
WHERE condition_on_index
LIMIT 1001
) as truncated_count;
在这种情况下,只要有足够的行满足条件,MySQL就会停止。