Mysql计数查询优化

Mysql计数查询优化,mysql,sql,query-optimization,Mysql,Sql,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秒之间 我

我有下面的查询要优化

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
你可以试试:

SELECT count(*) AS count 
  FROM area 
  JOIN entity
    ON entity.id = area.id
   AND entity.deleted = 0 
  JOIN areacust 
    ON areacust.id = area.id 
在可能的情况下,我喜欢在连接中包含条件,并将我要连接的表保持在这些条件中的等式的左边

而且
WHERE area.id>0
也很奇怪。。由于其他表中的自动增量ID,大多数外键从1开始,因此这将包括所有行。我已删除此条件

从解释的外观来看,您并不希望最上面一行使用
实体\u已删除\u idx
。对于
实体

以下是我对此查询的索引:

  • 区域
    -(id)这可能已经是主要区域了
  • areacust
    -(id)这可能已经是主要的
  • 实体
    -(id,已删除)应添加并使用该实体
更新

从表
实体
中删除除主索引和复合索引之外的所有未启用的索引

如果这不起作用,请运行:

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 

根据评论,如果您想继续查询,您必须为您的MySQL实例分配更多资源。我假设您使用InnoDB作为存储引擎,否则这个建议是无用的:

增加
innodb\u buffer\u pool
变量的值。尽你所能。您希望分配尽可能多的RAM

另外,去掉
deleted
列上的索引,它是无用的。它的基数太低,无法作为索引

您可以(应该)使用的另一种“技术”是手动处理此计数

创建包含您感兴趣的计数的表。每次更新/插入/删除实体或区域记录时-手动更新计数值(增加、减少)


这样,您所要做的就是查找单个表的单个记录。设置将自动排序的触发器应该很简单。这样,您将在运行时处理计数,而不是浪费I/O和CPU来不断遍历数据集。

Post
EXPLAIN
查询计划您是否尝试添加强制索引。。。。。选择?如何在此查询中从区域力索引(area.id)添加力索引。。因此,首先,如果您想计算所有内容,大多数人会将其写成
count(*)
。。如果只想计算一个表中的内容,可以执行
count(a.id)
甚至
(a.*)
。。但是,只有当有
左连接导致额外的行时,这才有意义。。。MySQL对
COUNT(ID)
COUNT(*)
的执行几乎相同。。除非存在要计数的
null
值。。。如果存在空值,您应该始终使用
COUNT(*)
,因为MySQL知道如何更好地处理它。。将执行时间减半。花费相同的时间甚至更多。@RahulTailwal很公平。。您是否在(id,deleted)上尝试了复合索引?大多数优化器将为此查询和原始查询生成相同的计划。这些在语义上是相同的,所以…@Clockwork Muse是的,这可能是真的,但是通过这个查询,更容易看到潜在的索引和速度,因此我的结论是。这需要时间的原因是因为您的数据库是HDD绑定的。它只是使用了硬盘I/O,因为它无法将工作数据集放入内存中。罪魁祸首总是
innodb\u buffer\u pool
value,如果您使用innodb(您应该这样做)。将该数字至少增加到服务器内存的70%(是的,70%,您希望内存中有尽可能多的数据,因为这是提高速度的方法)。我喜欢在增加资源之前,尽可能使用索引优化查询。。但这可能是他唯一的选择。就像汇总表的想法一样,超级快速。索引在这里帮不上忙。它们不是一种神奇的药丸,能让一切都像那样快速。这是一个简单的数据结构,在本例中,在
已删除的
上设置索引根本没有帮助。无法使用索引进一步优化原始查询。唯一可用的优化是删除
已删除的
上的索引,这只会释放一些存储空间。性能将是相同的。真正的答案是增加资源(innodb_buffer_pool的默认值是8MB,这太低了),或者创建一个表来查找计数器号。索引在这里绝对有帮助!我的回答中描述的索引涵盖了查询所需的所有信息,因此可以满足计数(*),而无需引擎进入行中检查实体删除值。。如果实体有很多列,这将节省大量内存。增加内存大小很好,但只能增加一次,而且不断升级服务器的成本很高,因此您希望查询尽可能快。这就是我喜欢汇总表的原因。。可移植的解决方案。另外,如果你看他的解释,看起来优化者在实体主键上使用删除的索引,即cray!我想先解决这个问题。