简体   繁体   English

MySQL计数查询优化

[英]Mysql Count query optimization

I have the below query to optimize. 我有以下查询要优化。

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

There are indexes on deleted, ids on all the tables. 在所有表上都有已删除索引,id。

Now when i have suppose 20 Lac (2 million) of records then the query takes lots of time to give me the result. 现在,当我假设有20个Lac(200万个)记录时,该查询将花费大量时间才能得出结果。 Its between 10 to 20 seconds. 它在10到20秒之间。

How can i optimize it more. 我如何进一步优化它。 Also is there any other technique to get count. 还有没有其他技术可以计数。

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

New explain for composite key 复合键的新说明

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

As per comments, if you want to keep the query in question - you have to allocate more resources to your MySQL instance. 根据注释,如果您想保持查询的状态-您必须为您的MySQL实例分配更多资源。 I am assuming you use InnoDB for storage engine, otherwise this advice is useless: 我假设您将InnoDB用于存储引擎,否则此建议无用:

Increase the value of innodb_buffer_pool variable. 增加innodb_buffer_pool变量的值。 As much as you can. 尽你所能地。 You want to allocate as much RAM as possible. 您想要分配尽可能多的RAM。

Also, get rid of index on deleted column, it's useless. 此外,摆脱deleted列上的索引,这是没有用的。 Its cardinality is too low for it to be an index. 它的基数太低,无法作为索引。

The other "technique" that you can (should) use is taking care of this count manually. 您可以(应该)使用的另一种“技术”是手动处理此计数。

Create the table that holds the count number you are interested in. Every time you update / insert / delete the entity or area record - update the count value manually (increase, decrease). 创建包含您感兴趣的计数编号的表。每次更新/插入/删除实体或区域记录-手动更新计数值(增加,减少)。

That way all you have to do is look up a single record of a single table. 这样,您要做的就是查找单个表的单个记录。 Setting up triggers that will sort this out automatically should be trivial. 设置将自动解决此问题的触发器应该很简单。 That way you'll take care of the count at runtime instead waste I/O and CPU to constantly traverse the data set. 这样,您将在运行时处理计数,而不是浪费I / O和CPU来不断遍历数据集。

You could try: 您可以尝试:

SELECT count(*) AS count 
  FROM area 
  JOIN entity
    ON entity.id = area.id
   AND entity.deleted = 0 
  JOIN areacust 
    ON areacust.id = area.id 

I like to include conditions in JOINs where possible and keep the table I'm JOINing on the left of the equals in these conditions. 我希望在可能的情况下在JOIN中包含条件,并在这些条件下将要加入的表保持在等号的左侧。

Also the WHERE area.id > 0 was strange.. most foreign_keys start at 1 due to auto_increment ids in other tables so this will include all rows. 同样WHERE area.id > 0也很奇怪..由于其他表中的auto_increment id,大多数foreign_keys从1开始,因此它将包括所有行。 I have deleted this condition. 我已删除此条件。

From the look of your explain, you don't really want the top row to be using entity_deleted_idx . 从您的解释来看,您实际上并不希望最上面的行使用entity_deleted_idx You may get more joy with a composite index on (id, deleted) for entity entity (id, deleted)上使用复合索引可能会带来更多乐趣

These are the indexes i'd have for this query: 这些是我对此查询的索引:

  • area - (id) This is probably the PRIMARY already area -(id)这可能已经是PRIMARY
  • areacust - (id) This is probably the PRIMARY already areacust (id)这可能已经是PRIMARY
  • entity - (id, deleted) This should be added and used. entity -(标识,已删除)应添加和使用。

UPDATE UPDATE

Remove all unsused indexes from the table entity except for the PRIMARY and the composite index. 从表entity删除所有未使用的索引,但PRIMARY和复合索引除外。

If that doesn't work run: 如果那不起作用,请运行:

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.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM