MySQL 有效测试是否计数 w/ where 大于一个值
MySQL efficient test if count w/ where is greater than a value
有没有办法优化以下查询?
SELECT count(*)>1000 FROM table_with_lot_of_rows WHERE condition_on_index;
使用此查询,MySQL 首先执行 count(*)
,然后进行比较。当只有几行满足条件时,这是很快的,但如果很多行满足条件,则可能需要很长时间。有没有办法在找到 1000 个项目后立即停止计数,而不是遍历所有结果?
特别是,我对具有全文条件的 MyISAM table 感兴趣,但 InnoDB and/or 基本 WHERE 子句的任何答案都会有所帮助。
您可以使用带有 LIMIT 的子查询来优化查询:
SELECT count(*)>1000 FROM (
SELECT 0 table_with_lot_of_rows
WHERE condition_on_index
LIMIT 1001
) as truncated_count;
在这种情况下,MySQL 只要有足够多的行满足条件就停止。
SELECT 1
FROM table_with_lot_of_rows
WHERE condition_on_index
LIMIT 1000, 1;
这样工作:
- 使用索引(大概比使用数据快)
- 跳过 1000 行,收集无。 (这比其他答案更好。)
- 如果你做到这一点,获取 1 行,仅包含文字
1
(在 SELECT
中)。
现在您要么有一个空结果集(<= 1000 行),要么有一行 1
(至少 1001 行)。
然后,根据您的应用程序语言,很容易区分这两种情况。
另一个注意事项:如果这是一个更大查询中的子查询,那么做
EXISTS ( SELECT 1
FROM table_with_lot_of_rows
WHERE condition_on_index
LIMIT 1000, 1 )
其中returns TRUE/FALSE(与1或0同义)。
面对现实吧,扫描 1001 行,即使是索引,也需要 一些 时间。我认为我的公式是最快的。
要检查的其他事项:这是 InnoDB 吗? EXPLAIN
是说 "Using index" 吗?多少内存? innodb_buffer_pool_size
的设置是什么?
请注意,InnoDB 现在具有 FULLTEXT,因此没有理由坚持使用 MyISAM。
如果您使用的是 MyISAM 而 WHERE
是 MATCH...
,那么我所说的大部分内容可能都不适用。 FULLTEXT
可能 在让引擎的其余部分有机会使用 ORDER BY
和 LIMIT
进行这些游戏之前获取所有结果。
请向我们展示实际的查询,它的 EXPLAIN
和 SHOW CREATE TABLE
。真正的目标是什么?要查看查询是否会提供 "too many" 个结果?
可能的改进(取决于上下文)
由于我的初始 SELECT
returns 标量 1
或 NULL
,它可以在任何布尔上下文中使用,例如 WHERE
。 1
是 TRUE
,NULL
将被视为 FALSE
。因此 EXISTS
可能是多余的。
另外,1
/NULL
可以变成1
/0
。注意:需要额外的括号。
IFNULL( ( SELECT ... LIMIT 1000,1 ), 0)
有没有办法优化以下查询?
SELECT count(*)>1000 FROM table_with_lot_of_rows WHERE condition_on_index;
使用此查询,MySQL 首先执行 count(*)
,然后进行比较。当只有几行满足条件时,这是很快的,但如果很多行满足条件,则可能需要很长时间。有没有办法在找到 1000 个项目后立即停止计数,而不是遍历所有结果?
特别是,我对具有全文条件的 MyISAM table 感兴趣,但 InnoDB and/or 基本 WHERE 子句的任何答案都会有所帮助。
您可以使用带有 LIMIT 的子查询来优化查询:
SELECT count(*)>1000 FROM (
SELECT 0 table_with_lot_of_rows
WHERE condition_on_index
LIMIT 1001
) as truncated_count;
在这种情况下,MySQL 只要有足够多的行满足条件就停止。
SELECT 1
FROM table_with_lot_of_rows
WHERE condition_on_index
LIMIT 1000, 1;
这样工作:
- 使用索引(大概比使用数据快)
- 跳过 1000 行,收集无。 (这比其他答案更好。)
- 如果你做到这一点,获取 1 行,仅包含文字
1
(在SELECT
中)。
现在您要么有一个空结果集(<= 1000 行),要么有一行 1
(至少 1001 行)。
然后,根据您的应用程序语言,很容易区分这两种情况。
另一个注意事项:如果这是一个更大查询中的子查询,那么做
EXISTS ( SELECT 1
FROM table_with_lot_of_rows
WHERE condition_on_index
LIMIT 1000, 1 )
其中returns TRUE/FALSE(与1或0同义)。
面对现实吧,扫描 1001 行,即使是索引,也需要 一些 时间。我认为我的公式是最快的。
要检查的其他事项:这是 InnoDB 吗? EXPLAIN
是说 "Using index" 吗?多少内存? innodb_buffer_pool_size
的设置是什么?
请注意,InnoDB 现在具有 FULLTEXT,因此没有理由坚持使用 MyISAM。
如果您使用的是 MyISAM 而 WHERE
是 MATCH...
,那么我所说的大部分内容可能都不适用。 FULLTEXT
可能 在让引擎的其余部分有机会使用 ORDER BY
和 LIMIT
进行这些游戏之前获取所有结果。
请向我们展示实际的查询,它的 EXPLAIN
和 SHOW CREATE TABLE
。真正的目标是什么?要查看查询是否会提供 "too many" 个结果?
可能的改进(取决于上下文)
由于我的初始 SELECT
returns 标量 1
或 NULL
,它可以在任何布尔上下文中使用,例如 WHERE
。 1
是 TRUE
,NULL
将被视为 FALSE
。因此 EXISTS
可能是多余的。
另外,1
/NULL
可以变成1
/0
。注意:需要额外的括号。
IFNULL( ( SELECT ... LIMIT 1000,1 ), 0)