0

実行に少なくとも 1 分かかるこのクエリがあります。多くの左結合を使用します。それを速くする方法はありますか?私は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')
4

1 に答える 1

2

そうですね、自分にできることをやってみました。ほとんどの場合、いくつかの並べ替え、INNER JOIN へのスワップ、および 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%'、インデックスは使用できません

于 2013-06-11T12:00:42.400 に答える