好吧,我在mysql中并不出色,但我知道索引可以帮助我,但是我已经做了一些插件而找不到帮助......
有人有任何想法吗?
explain
select `users_usr`.`id_usr` AS `id_usr`,
`users_usr`.`firstname_usr` AS `firstname_usr`,
`users_usr`.`lastname_usr` AS `lastname_usr`,`users_usr`.`social_usr` AS `social_usr`,`users_usr`.`address1_usr` AS `address1_usr`,
`users_usr`.`address2_usr` AS `address2_usr`,`users_usr`.`city_usr` AS `city_usr`,`users_usr`.`state_usr` AS `state_usr`,`users_usr`.`zip_usr` AS `zip_usr`,
`users_usr`.`email_usr` AS `email_usr`,`credit_acc`.`given_credit_acc` AS `given_credit_acc`,`credit_acc`.`credit_used_acc` AS `credit_used_acc`,
`credit_acc`.`date_established_acc` AS `date_established_acc`,`credit_acc`.`type_acc` AS `type_acc`,`credit_acc`.`bureau_status_acc` AS `bureau_status_acc`,
sum((`credit_balance`.`debit_acc` - `credit_balance`.`credit_acc`)) AS `balance`
from (((`users_usr`
left join `credit_acc` on((`users_usr`.`id_usr` = `credit_acc`.`uid_usr`)))
left join `cfc_cfc` on((`credit_acc`.`id_cfc` = `cfc_cfc`.`id_cfc`)))
join `credit_acc` `credit_balance` on((`credit_balance`.`credit_used_acc` = `credit_acc`.`id_acc`)))
where ((`credit_acc`.`type_acc` = _latin1'init')
and (`credit_acc`.`status_acc` = _latin1'active')
and (`credit_acc`.`linetype_acc` = _latin1'personal'))
group by `credit_balance`.`credit_used_acc` order by `users_usr`.`id_usr`
给我
id select_type table type possible_keys key key_len ref rows Extra
------ ----------- -------------- ------ ----------------------------------- --------------- ------- --------------------------------- ------ -------------------------------
1 SIMPLE credit_balance index credit_used_acc,cash_report_index credit_used_acc 40 (NULL) 14959 Using temporary; Using filesort
1 SIMPLE credit_acc eq_ref PRIMARY,type_acc,type_acc_2,uid_usr PRIMARY 8 cc.credit_balance.credit_used_acc 1 Using where
1 SIMPLE cfc_cfc eq_ref PRIMARY PRIMARY 4 cc.credit_acc.id_cfc 1 Using index
1 SIMPLE users_usr eq_ref PRIMARY,id_usr PRIMARY 4 cc.credit_acc.uid_usr 1
Table Non_unique Key_name Seq_in_index Column_name Collation Cardinality Sub_part Packed Null Index_type Comment
---------- ---------- ----------------- ------------ ----------------------- --------- ----------- -------- ------ ------ ---------- -------
credit_acc 0 PRIMARY 1 id_acc A 14016 (NULL) (NULL) BTREE
credit_acc 1 type_acc 1 type_acc A 11 (NULL) (NULL) YES BTREE
credit_acc 1 type_acc 2 date_acc A 14016 (NULL) (NULL) YES BTREE
credit_acc 1 type_acc 3 affiliate_aff A 14016 (NULL) (NULL) YES BTREE
credit_acc 1 type_acc_2 1 type_acc A 11 (NULL) (NULL) YES BTREE
credit_acc 1 type_acc_2 2 date_acc A 14016 (NULL) (NULL) YES BTREE
credit_acc 1 type_acc_2 3 complete_acc A 14016 (NULL) (NULL) YES BTREE
credit_acc 1 type_acc_2 4 commission_refunded_acc A 14016 (NULL) (NULL) YES BTREE
credit_acc 1 credit_used_acc 1 credit_used_acc A 14016 (NULL) (NULL) YES BTREE
credit_acc 1 credit_used_acc 2 id_acc A 14016 (NULL) (NULL) BTREE
credit_acc 1 credit_used_acc 3 type_acc A 14016 (NULL) (NULL) YES BTREE
credit_acc 1 uid_usr 1 uid_usr A 7008 (NULL) (NULL) YES BTREE
credit_acc 1 cash_report_index 1 credit_used_acc A 7008 (NULL) (NULL) YES BTREE
credit_acc 1 cash_report_index 2 type_acc A 14016 (NULL) (NULL) YES BTREE
credit_acc 1 cash_report_index 3 date_established_acc A 14016 (NULL) (NULL) YES BTREE
答案 0 :(得分:0)
您的EXPLAIN输出显示您已经拥有可能有用的索引,但查询引擎已决定不使用它们。
http://dev.mysql.com/doc/refman/5.0/en/using-explain.html说:
使用临时
要解决查询,MySQL需要 创建一个临时表来保存 结果。这通常发生在 查询包含GROUP BY和ORDER BY 以不同方式列出列的子句。
您的查询包括:
GROUP BY `credit_balance`.`credit_used_acc`
ORDER BY `users_usr`.`id_usr`
您可以在这两个子句中命名不同的列,因此这意味着查询需要临时表并在磁盘上对其结果进行排序。磁盘I / O是SQL性能的主要敌人。这可能比通过应用索引可以弥补的性能更有害。
所以我建议尝试删除ORDER BY
子句,看看它是否摆脱了“使用临时”评论。
编辑好的,我已经做了一些测试,并且更仔细地查看了你的表格。
我认为你有很多冗余的索引,并不适用于当前的查询。它可能是索引对其他一些查询有用,或者它们可能只是实验中的遗留物。
有一种观察结果是您加入cfc_cfc
是不必要的,但我从您的评论中看到您已将其删除。但它似乎没有修复EXPLAIN报告。
另一个观察是你的LEFT JOIN
是不必要的;它可能是INNER JOIN
,因为无论如何,这些列的WHERE
子句中都有条件。它不是外连接的目的,外连接往往更慢。
索引可能对您在连接条件,行限制或GROUP BY或ORDER BY子句中使用的列有用。 MySQL在给定查询中不能为每个表使用多个索引,因此定义复合索引是有意义的。但是您应该在查询中使用的列上定义索引。如果您只使用三列索引的第2列和第3列(即不是索引中的第一列),则索引无效。
当然,所有主键和外键约束都隐式创建了索引,但这是我创建的唯一额外索引:
KEY columns_used_in_query (uid_usr, type_acc, status_acc, linetype_acc),
如果您将条件放在WHERE
子句或连接条件中,则优化计划无关紧要,只要它们不属于外连接的条件即可。但我确实注意到所有其他条件相同,优化器似乎根据您首先定义的索引选择一个索引!
我还没有淘汰临时表和文件在EXPLAIN报告中注释,但我认为这些更改将加快查询速度。
答案 1 :(得分:0)
收回部分内容,然后重新开始。
以下是我对您的查询的解释。
uu.select uu.id_usr,
uu.firstname_usr,
uu.lastname_usr,
uu.social_usr,
uu.address1_usr,
uu.address2_usr,
uu.city_usr,
uu.state_usr,
uu.zip_usr,
uu.email_usr,
ca.given_credit_acc,
ca.credit_used_acc,
ca.date_established_acc,
ca.type_acc,
ca.bureau_status_acc,
sum(cb.debit_acc - cb.credit_acc) AS `balance`
from users_usr AS uu
left join credit_acc AS ca on uu.id_usr = ca.uid_usr
join credit_acc AS cb on ca.credit_used_acc = ca.id_acc
where ca.type_acc = 'init'
and ca.status_acc = 'active'
and ca.linetype_acc = 'personal'
group by cb.credit_used_acc
order by uu.id_usr
答案 2 :(得分:0)
您的查询(带有连接,轮组,组和排序的可优化部分)可以简化为:
SELECT
uu.select uu.id_usr,
ca.given_credit_acc,
ca.credit_used_acc,
ca.type_acc,
sum(cb.debit_acc - cb.credit_acc) AS `balance`
FROM
users_usr AS uu
LEFT JOIN
credit_acc AS ca on uu.id_usr = ca.uid_usr
AND ca.type_acc = 'init'
AND ca.status_acc = 'active'
AND ca.linetype_acc = 'personal'
-- credit_acc needs an index on uid_usr + type_acc _ status_acc
JOIN
credit_acc AS cb on ca.credit_used_acc = ca.id_acc
-- credit_acc needs an index on credit_used_acc
GROUP BY cb.credit_used_acc
ORDER BY uu.id_usr
请注意,我接受了WHERE子句并将其移入JOIN - MySQL似乎喜欢这种调整。
请注意有关索引的注释。看看你是否可以简化工作(和优化),然后再添加其他字段。
你觉得怎么样,比尔?