2013-06-11 5 views
0

У меня есть этот запрос, который занимает не менее 1 минуты для запуска. Он использует много левых объединений. Есть ли способ сделать это быстрее? Я новичок в SQL, поэтому помощь будет оценена.Можем ли мы оптимизировать этот SQL-запрос?

SELECT 
    distinct cnt.last_name, 
    cnt.bus_ph_num, 
    cnt.email_addr, 
    usr.login, 
    cnt.fst_name, 
    cnt.fk_id 
from 
    contact cnt 
LEFT JOIN 
    transaction tran 
     ON tran.id=cnt.fk_id  
left join 
    party party 
     on party.pk_id=cnt.fk_id 
left join 
    user usr 
     on usr.fk_id=cnt.fk_id 
left join 
    role role 
on  
    usr.role_id = role.pk_row_id 
where 
    cnt.status_cd=1 
    and party.fk_id= 'xyz' 
    and (
     usr.login like '%somevalue%' 
     and (
      tran.txn_trk_num is null || tran.txn_trk_num like '%somevalue%' 
     ) 
     and cnt.last_name like '%somevalue%' 
     and cnt.email_addr like '%somevalue%' 
     and cnt.busin_ph_num like '%somevalue%'  
    ) 
    and (
     tran.txn_trk_num is null || tran.txn_typ=1 || tran.txn_typ=2 || tran.txn_typ=3 
    ) 
    and (role.role_name ='ROLE_ADMIN') 
+0

это не проблемный человек .... попробуйте это http://blog.sqlauthority.com/2009/01/20/sql-server-rules-for-optimizining-any-query-best-practices-for-query-optimization/ или http://www.codeproject.com/Articles/35665/Top-10-steps-to-optimize-data-access-in-SQL-Server –

+1

как «%» соответствует всем, так почему это так в вашем запросе? –

+1

Также верно, что «tran.txn_trk_num имеет значение null || tran.txn_trk_num, как«% », немного глупо, поскольку он ищет значение NULL, которое соответствует чему угодно. Если вы можете предоставить информацию о предполагаемых отношениях между этими таблицами/ожидаемыми результатами, тогда это было бы полезно –

ответ

2

Право Я старался делать все, что в моих силах. В основном, некоторая переупорядоченность, некоторая замена на INNER JOINs и перемещение синтаксиса WHERE в соединения. Некоторое переименование псевдонимов, потому что вы использовали псевдонимы, соответствующие именам таблиц, отрицая их цель.

Это будет возвращать строки, в которых нет соответствующих транзакций, поэтому вы можете захотеть изменить это соединение как INNER, а скорее зависит от цели/предполагаемого выхода, но это должно быть хорошей отправной точкой. Это позволяет MySQL сократить количество строк, на которые он смотрит.

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

SELECT DISTINCT 
    cnt.last_name, 
    cnt.bus_ph_num, 
    cnt.email_addr, 
    u.login, 
    cnt.fst_name, 
    cnt.fk_id 

FROM contact cnt 

-- Changed to INNER JOIN as the WHERE indicates this is required 
INNER JOIN party p 
    ON p.pk_id=cnt.fk_id 
    -- Moved this limiting statement to the join 
    AND p.fk_id= 'xyz' 

-- Changed to INNER JOIN as the LIKE % indicates htis is required 
INNER JOIN user u 
    ON u.fk_id=cnt.fk_id 
    -- OP added later, quite inefficient due to use of wildcards on both sides causing scans 
    AND u.login LIKE '%somevalue%' 

-- Also here, INNER, as the WHERE means this is required 
INNER JOIN role r 
    ON r.pk_row_id = u.role_id 
    -- Moved this limiting statement to the join 
    AND r.role_name ='ROLE_ADMIN' 

LEFT JOIN transaction tran 
    ON tran.id=cnt.fk_id 
    -- Moved this limiting statement to the join 
    AND tran.txn_typ IN (1 , 2 , 3) 
    -- OP added later, quite inefficient due to use of wildcards on both sides causing scans 
    AND tran.txn_trk_num LIKE '%somevalue%' 

WHERE cnt.status_cd = 1 
    -- OP added later, quite inefficient due to use of wildcards on both sides causing scans 
    AND cnt.last_name LIKE '%somevalue%' 
    AND cnt.email_addr LIKE '%somevalue%' 
    AND cnt.busin_ph_num LIKE '%somevalue%' 

Если вы можете избавиться от этих LIKE заявления он получит лучше также. Следующие способны использовать индекс, если подходящий один доступен:

  • ... LIKE 'somevalue'
  • ... = 'somevalue'
  • ... LIKE 'somevalue%'

Однако ... LIKE '%somevalue%' не может использовать индекс

+0

Большое спасибо :) – user2434

+1

Это последнее ЛЕВОЕ ПРИСОЕДИНЕНИЕ, вероятно, должно быть ИНТЕРНЕЙШЕЙ ПРИСОЕДИНЕНИЕМ, хотя это я предполагаю, что вас не интересует результат, если нет соответствующих транзакций :) –

Смежные вопросы