【发布时间】:2019-10-01 16:17:19
【问题描述】:
例如,我有下表:
table Product
------------
id
category_id
processed
product_name
此表在列 id category_id 和 processed 和 (category_id, proccessed) 上有索引。该表的统计数据为:
select count(*) from Product; -- 50M records
select count(*) from Product where category_id=10; -- 1M records
select count(*) from Product where processed=1; -- 30M records
我想查询的最简单的查询是:(必须选择*)。
select * from Product
where category_id=10 and processed=1
order by id ASC LIMIT 100
上面的无限制查询只有大约10,000条记录。
我想多次调用上述查询。每次我出去时,我都会将字段 processed 更新为 0。(因此它不会出现在下一个查询中)。当我在真实数据上进行测试时,有时优化器会尝试使用id作为key,因此花费了很多时间。
如何优化上述查询(一般而言)
P/S:为了避免混淆,我知道最好的索引应该是(类别、已处理、id)。但我无法更改索引。我的问题只是与优化查询有关。
谢谢
【问题讨论】:
-
这个链接对索引提示真的很有帮助:mysql.rjweb.org/doc.php/index_cookbook_mysql 和 Gordon 的回答应该会给你最好的性能
-
试试
force index (processed) -
为了防止 MySQL 使用前导列为
id的索引(即使用索引来避免“使用文件排序”操作),我们将 ORDER BY 子句更改为对表达式进行操作,而不是一个光秃秃的柱子。例如,如果id是数字类型,我们可以使用ORDER BY id + 42 ASC。如果id数据类型为日期、日期时间等,我们可以使用ORDER BY id + INTERVAL 42 DAY ASC。如果是字符类型,我们可以ORDER BY CONCAT('42',id) ASC -
@spencer7593 感谢您提供这些信息。你能帮我解释一下为什么吗?是否有任何消息来源提到这一点。谢谢。
-
dev.mysql.com/doc/refman/8.0/en/select-optimization.html 特别是关于使用索引来满足 ORDER BY 的部分。当一个索引不能被使用时,有一个 Using filesort 操作。这在大型设备上可能会很昂贵。如果优化器使用前导列为
id的索引,那么它必须使用该索引来满足 ORDER BY ... 优化器必须认为按顺序检查每一行会更快,并确定它是否满足 WHERE 条件,找到 100 行后停止。 MySQL 不能使用索引来满足 ORDER BY 表达式。