SQL:使用索引优化大表上的查询

时间:2019-10-01 16:17:19

标签: mysql sql mariadb

例如,我有下表:

table Product
------------
id
category_id 
processed
product_name

此表在id category_idprocessed(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)。但是我无法更改索引。我的问题只是与优化查询有关。

谢谢

2 个答案:

答案 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提供了一种快速的方法。