[英]Mysql Count query optimization
我有以下查询要优化。
SELECT count(*) AS count FROM area
INNER JOIN entity ON area.id = entity.id
INNER JOIN areacust ON area.id = areacust.id
WHERE entity.deleted=0
AND area.id > 0
在所有表上都有已删除索引,id。
现在,当我假设有20个Lac(200万个)记录时,该查询将花费大量时间才能得出结果。 它在10到20秒之间。
我如何进一步优化它。 还有没有其他技术可以计数。
id select_type table type possible_keys key key_len ref rows Extra
1 SIMPLE vtiger_crmentity ref PRIMARY,entity_deleted_idx entity_deleted_idx 4 const 729726 Using where; Using index
1 SIMPLE area eq_ref PRIMARY PRIMARY 4 area.id 1 Using index
1 SIMPLE areacust eq_ref PRIMARY PRIMARY 4 area.id 1 Using where; Using index
复合键的新说明
id select_type table type possible_keys key key_len ref rows Extra
1 SIMPLE entity ref PRIMARY,entity_deleted_idx,comp_index deleted_idx 4 const 928304 Using index
1 SIMPLE area eq_ref PRIMARY PRIMARY 4 entity.id 1 Using index
1 SIMPLE areacust eq_ref PRIMARY PRIMARY 4 entity.idid 1 Using index
根据注释,如果您想保持查询的状态-您必须为您的MySQL实例分配更多资源。 我假设您将InnoDB用于存储引擎,否则此建议无用:
增加innodb_buffer_pool
变量的值。 尽你所能地。 您想要分配尽可能多的RAM。
此外,摆脱deleted
列上的索引,这是没有用的。 它的基数太低,无法作为索引。
您可以(应该)使用的另一种“技术”是手动处理此计数。
创建包含您感兴趣的计数编号的表。每次更新/插入/删除实体或区域记录-手动更新计数值(增加,减少)。
这样,您要做的就是查找单个表的单个记录。 设置将自动解决此问题的触发器应该很简单。 这样,您将在运行时处理计数,而不是浪费I / O和CPU来不断遍历数据集。
您可以尝试:
SELECT count(*) AS count
FROM area
JOIN entity
ON entity.id = area.id
AND entity.deleted = 0
JOIN areacust
ON areacust.id = area.id
我希望在可能的情况下在JOIN中包含条件,并在这些条件下将要加入的表保持在等号的左侧。
同样WHERE area.id > 0
也很奇怪..由于其他表中的auto_increment id,大多数foreign_keys从1开始,因此它将包括所有行。 我已删除此条件。
从您的解释来看,您实际上并不希望最上面的行使用entity_deleted_idx
。 在entity
(id, deleted)
上使用复合索引可能会带来更多乐趣
这些是我对此查询的索引:
area
-(id)这可能已经是PRIMARY areacust
(id)这可能已经是PRIMARY entity
-(标识,已删除)应添加和使用。 UPDATE
从表entity
删除所有未使用的索引,但PRIMARY和复合索引除外。
如果那不起作用,请运行:
SELECT count(*) AS count
FROM area
JOIN entity USE INDEX (**composite_index_name**)
ON entity.id = area.id
AND entity.deleted = 0
JOIN areacust
ON areacust.id = area.id
声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.