помогите с индексом - PullRequest
       12

помогите с индексом

1 голос
/ 09 декабря 2008

Хорошо, я не очень хорош в 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 голосов
/ 09 декабря 2008

Отведите часть этого и начните все сначала.

Вот мое толкование вашего запроса.

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  
0 голосов
/ 09 декабря 2008

Ваш запрос (оптимизируемая часть с объединениями, группами, группами и сортировками) может быть упрощен до:

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, похоже, нравится такая настройка.

Обратите внимание на комментарии об индексах. Посмотрите, сможете ли вы заставить это упрощение работать (и оптимизировать), а затем добавьте остальные поля.

Что ты думаешь, Билл?

0 голосов
/ 09 декабря 2008

Ваш вывод 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`

Вы называете разные столбцы в этих двух пунктах, поэтому это означает, что для запроса требуется временная таблица и результаты сортируются на диске. Дисковый ввод-вывод - главный враг производительности SQL. Это, вероятно, вредит производительности, чем вы можете восполнить, применяя индекс.

Так что я бы предложил попробовать удалить предложение ORDER BY и посмотреть, избавится ли оно от комментария «использование временного».

edit Хорошо, я сделал еще несколько тестов и более внимательно посмотрел на ваши таблицы.

Я думаю, что у вас есть много индексов, которые являются избыточными и не применимы к этому текущему запросу. Это могут быть индексы, полезные для какого-либо другого запроса, или они могут быть просто остатками ваших экспериментов.

Одно наблюдение состоит в том, что ваше присоединение к 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, но я думаю, что эти изменения ускорят запрос.

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...