Mysql查询性能使用group by使用聚合计数{> 100万用户}

时间:2015-12-17 06:25:59

标签: mysql sql performance query-performance

查询:

select count(*) as col_0_0_, usertb0_.ACCT_STATUS_ID as col_1_0_, usertb0_.user_type as col_2_0_ 
from user_tbl usertb0_ 
inner join 
user_org_xref userorgxre1_ 
on usertb0_.USER_ID=userorgxre1_.USER_ID 
where 
(userorgxre1_.ORGANIZATION_ID in (2)) and (usertb0_.ACCT_STATUS_ID in (1 , 11 , 13 , 15 , 2)) 
group by usertb0_.ACCT_STATUS_ID , usertb0_.user_type;

表&索引:

user_tbl ( PK: user_id) (Index: {user_id}, {ACCT_STATUS_ID},covered index:{ ACCT_STATUS_ID,user_type})
user_org_xref (pk: user_org_id, FK: user_id) (index {organization_id},{user_id})

以上查询需要20秒的时间才能执行,任何人都可以帮助我提高性能

当并行命中时间超过30秒时。

查询解释:

enter image description here

enter image description here

2 个答案:

答案 0 :(得分:0)

EXPLAIN输出中的查询计划与图中的不同。 EXPLAIN计划使用user_tbl.cc_uid_sts_type索引进行范围选择(可能是在ACCT_STATUS_ID上),从中检索481k行。然后它使用USER_ID_FK_idx索引连接到user_org_xref。如果这不包括organisation_id,那么添加它将加快性能。

图表计划使用ORG_ID_FK索引(在user_org_xref.organisation_id上)来检索499k行。然后,它使用主键索引连接到user_tbl,从而使用正确的ACCT_STATUS_ID将组织用户过滤到249k行。

最终,无论您采用哪种方式开始查询,都必须处理大量数据。在给定的组织中有近50万用户,并且具有相同数量的用户具有正确的ACCT_STATUS_ID。因此,如果您确实需要提高性能,则可能需要以某种方式进行非规范化,例如将ACCT_STATUS_ID复制到user_org_xref表,尽管这显然是一个理想情况下要避免的极端解决方案。

答案 1 :(得分:0)

我尝试了几种方法,实际上,最好的设置是在查询的每个表上强制一个索引。它在4秒内完成了工作......

这些是索引和最终查询:

CREATE INDEX <index_name_1> ON user_tbl (acct_status_id, user_type, user_id);

CREATE INDEX <index_name_2> ON user_org_xref (organization_id, user_id);

SELECT 
  COUNT(*) AS col_0_0_, 
  usertb0_.acct_status_id AS col_1_0_, 
  usertb0_.user_type AS col_2_0_ 
FROM user_tbl AS usertb0_ FORCE INDEX (<index_name_1>) 
INNER JOIN user_org_xref AS userorgxre1_ FORCE INDEX (<index_name_2>) ON 1=1
  AND userorgxre1_.user_id = usertb0_.user_id
WHERE 1=1
  AND userorgxre1_.organization_id IN (2)
  AND usertb0_.acct_status_id IN (1, 2, 11, 13, 15) 
GROUP BY 
  usertb0_.acct_status_id, 
  usertb0_.user_type
;