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;

这样工作:

  1. 使用索引(大概比使用数据快)
  2. 跳过 1000 行,收集。 (这比其他答案更好。)
  3. 如果你做到这一点,获取 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 而 WHEREMATCH...,那么我所说的大部分内容可能都不适用。 FULLTEXT 可能 在让引擎的其余部分有机会使用 ORDER BYLIMIT 进行这些游戏之前获取所有结果。

请向我们展示实际的查询,它的 EXPLAINSHOW CREATE TABLE。真正的目标是什么?要查看查询是否会提供 "too many" 个结果?

可能的改进(取决于上下文)

由于我的初始 SELECT returns 标量 1NULL,它可以在任何布尔上下文中使用,例如 WHERE1TRUENULL 将被视为 FALSE。因此 EXISTS 可能是多余的。

另外,1/NULL可以变成1/0。注意:需要额外的括号。

IFNULL( ( SELECT ... LIMIT 1000,1 ), 0)