2016-05-28 13 views
1

私は初心者ですが、このクエリでいくつかのパフォーマンス上の問題があります。 ヒント?クエリは巨大なデータベース上で実行されています...SQL最適化のヒント

SELECT 
       z_screenshots.guid, 
       z_screenshots.player_name, 
       z_screenshots.server, 
       z_screenshots.map, 
       z_screenshots.created, 
       z_screenshots.uploaded, 
       z_screenshots.uploader_id, 
       z_screenshots.filesize 
      FROM z_screenshots 
      INNER JOIN (
       SELECT clients.guid 
       FROM clients WHERE clients.id NOT IN (
        SELECT clients.id 
        FROM clients 
        INNER JOIN (
         SELECT client_id 
         FROM penalties 
         WHERE penalties.inactive = 0 AND(penalties.type = 'Ban' OR (penalties.type = 'TempBan' AND FROM_UNIXTIME(penalties.time_expire) > NOW())) 
         GROUP BY penalties.client_id 
        ) penalties 
        ON clients.id = penalties.client_id 
       ) 
      ) clients 
      ON z_screenshots.guid = clients.guid 

      ORDER BY z_screenshots.uploaded DESC 
      LIMIT ?, ?; 
+0

ヒント番号1 - 'not in'が遅いです。他にもオプションがありますが、ロジックを一致させる必要があります。また、指定しなかったデータベースエンジンによって異なります。 –

答えて

2

クエリを書き直すことをお勧めします。あなたはclient_idあまりを持っていない場合は、このクエリでも大丈夫だろう

SELECT 
    s.guid, 
    s.player_name, 
    s.server, 
    s.map, 
    s.created, 
    s.uploaded, 
    s.uploader_id, 
    s.filesize 
FROM z_screenshots s 
INNER JOIN clients c ON s.guid = c.guid 
LEFT JOIN (
    SELECT DISTINCT client_id 
    FROM penalties 
    WHERE penalties.inactive = 0 
    AND (penalties.type = 'Ban' OR (penalties.type = 'TempBan' AND FROM_UNIXTIME(penalties.time_expire) > NOW())) 
) p ON c.id = p.client_id 
WHERE p.client_id IS NULL; 
ORDER BY s.uploaded DESC 
LIMIT ?, ?; 

SELECT 
    s.guid, 
    s.player_name, 
    s.server, 
    s.map, 
    s.created, 
    s.uploaded, 
    s.uploader_id, 
    s.filesize 
FROM z_screenshots s 
INNER JOIN clients c ON s.guid = c.guid 
WHERE c.id NOT IN 
(
    SELECT DISTINCT client_id 
    FROM penalties 
    WHERE penalties.inactive = 0 
    AND (penalties.type = 'Ban' OR (penalties.type = 'TempBan' AND FROM_UNIXTIME(penalties.time_expire) > NOW())) 
) 
ORDER BY s.uploaded DESC 
LIMIT ?, ?; 

インデックスに関しては、それは言うのは難しいです。 clients、これは非常に明確な値があるようには聞こえません。インデックスが優れている、この式の近い結果は、それが安いだと思いますあなたは5つの個別の値及び5000000行、(なぜならあなたLIMIT節の仮定)のMySQLを持っている1.

COUNT(DISTINCT <column>)/COUNT(<column>) 

意味になりますテーブル全体を読み込むだけです。これが当てはまる場合は、z_screenshots.uploadedにインデックスを持つことを検討してください。そうすれば、MySQLは少なくともソートする必要はありません。 EXPLAINを読んで、いつインデックスが選択され、どのインデックスであるかを知る。

+0

うわー、素敵で素早い答えをありがとう! P.S.それはMYSQLです(あなたが言ったように) –