帮助索引

时间:2008-12-08 21:24:10

标签: sql mysql

好吧,我在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              

3 个答案:

答案 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似乎喜欢这种调整。

请注意有关索引的注释。看看你是否可以简化工作(和优化),然后再添加其他字段。

你觉得怎么样,比尔?