例如,我有下表:
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
作为密钥,因此会花费很多时间。
如何优化上述查询(一般而言)
P / S:为避免混淆,我知道最好的索引应该是(类别,已处理,ID)。但是我无法更改索引。我的问题只是与优化查询有关。
谢谢
答案 0 :(得分:4)
对于此查询:
select *
from Product
where category_id = 10 and processed = 1
order by id asc
limit 100;
最佳索引位于product(category_id, processed, id)
上。这是一个由三部分组成的键的单个索引,键的顺序是这样。
答案 1 :(得分:0)
鉴于您拥有INDEX(category_id, processed)
,因此仅拥有INDEX(category_id)
实际上没有任何优势。 DROP
是后者。
可能具有将优化器推向复合INDEX(category_id, processed)
的有益副作用,这对于查询至少是“更好”的。
在不触摸索引的情况下,您可以 使用FORCE INDEX
来提及复合索引的名称。但我不建议这样做。 “它可能在今天有所帮助,但在数据更改后明天会受到伤害。”
为什么您说“但是我不能更改索引”?新版本的MySQL / MariaDB使ADD / DROP INDEX的速度比旧版本快得多。另外,pt-online-schema-change
提供了一种快速的方法。