MySQL 有效测试是否计数 w/ where 大于一个值

M1L*_*L0U 4 mysql count query-optimization where short-circuiting

有没有办法优化以下查询?

SELECT count(*)>1000 FROM table_with_lot_of_rows WHERE condition_on_index;
Run Code Online (Sandbox Code Playgroud)

使用此查询,MySQL 首先执行count(*),然后进行比较。当只有几行满足条件时,这很快,但如果很多行满足条件,则可能需要永远。有没有办法在找到 1000 个项目后立即停止计数,而不是查看所有结果?

特别是,我对带有全文条件的 MyISAM 表感兴趣,但是对 InnoDB 和/或基本 WHERE 子句的任何答案都会有所帮助。

Ric*_*mes 6

SELECT 1
    FROM table_with_lot_of_rows
    WHERE condition_on_index
    LIMIT 1000, 1;
Run Code Online (Sandbox Code Playgroud)

以这种方式工作:

  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 )
Run Code Online (Sandbox Code Playgroud)

返回 TRUE/FALSE(与 1 或 0 同义)。

面对现实,扫描 1001 行,甚至是索引,都需要一些时间。我认为我的配方是最快的。

要检查的其他事项:这是 InnoDB 吗?是否EXPLAIN说“使用索引”?多少内存?的设置是innodb_buffer_pool_size什么?

请注意,InnoDB 现在具有 FULLTEXT,因此没有理由坚持使用 MyISAM。

如果您使用的WHERE是MyISAM 并且是MATCH...,那么我所说的大部分内容可能不适用。 FULLTEXT 可能会先获取所有结果,然后再让引擎的其余部分有机会使用ORDER BY和进行这些游戏LIMIT

请向我们展示实际的查询、它的EXPLAIN、 和SHOW CREATE TABLE。真正的目标是什么?查看查询是否会提供“太多”的结果?

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

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

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

IFNULL( ( SELECT ... LIMIT 1000,1 ), 0)
Run Code Online (Sandbox Code Playgroud)