2017-04-04 4 views
2

は私がはEXPLAINでより少ない行を持っていますが、明示的なより遅いが

SELECT `publisher_id`, `publisher_name`, SUM(`views`) AS `total_views`, SUM(`channels`) AS `total_channels` 
FROM (
    SELECT DISTINCT `name` AS `publisher_name`, `id` AS `publisher_id` 
    FROM `publishers` 
    WHERE TRIM(`name`) <> '' 
    ) AS `publisher_names` 
    INNER JOIN 
    (
    SELECT `twitch_name`, `publishers` 
    FROM `game_profiles` 
    WHERE `twitch_name` IS NOT NULL 
     AND `publishers` IS NOT NULL 
     AND TRIM(`publishers`) <> '' 
    ) AS `game_list` 
    ON `game_list`.`publishers` LIKE CONCAT('%', `publisher_names`.`publisher_name`, '%') 
    INNER JOIN 
    (
    SELECT `games`.`id` AS `id`, `games`.`name`, `games`.`simple_name`, `games`.`box`, SUM(`channels`) AS `channels`, SUM(`viewers`) AS `views` 
    FROM `games` 
    WHERE `log_date` >= SUBDATE(NOW(), INTERVAL 1 WEEK) 
     AND `log_date` <= SUBDATE(NOW(), INTERVAL 0 WEEK) 
    GROUP BY `games`.`id` 
    ) AS `view_list` 
    ON `game_list`.`twitch_name` = `view_list`.`name` 
GROUP BY `publisher_id` ORDER BY `total_views` DESC LIMIT 10; 

と、クエリのパフォーマンスを確認する以下のクエリを最適化しようとして登録しよう EXPLAINコマンドを実行し、私は次のような結果を得ます。

EXPLAIN result for explicit JOIN

基本的にゲームテーブル、ビュー、および時間単位のチャンネル数が含まれ、game_profilesの表は、そのpubliisher(複数可)に、ゲームをマップし、出版テーブルは含まれてい既存の各出版社のより詳細な行私が達成しようとしているのは、過去1週間のゲームの総視聴回数に基づいてトップ10のパブリッシャーを表示することです。

アイデアがなくなり、暗黙的なJOINを使用しようとしました。クエリは私に EXPLAINコマンドをため次のような結果になります

SELECT `publishers`.`id` AS `publisher_id`, `publishers`.`name` AS `publisher_name`, 
SUM(`games`.`viewers`) AS `total_views`, SUM(`games`.`channels`) AS `total_channels` 
FROM `game_profiles`, `publishers`, `games` 
WHERE `game_profiles`.`twitch_name` IS NOT NULL 
    AND `game_profiles`.`publishers` IS NOT NULL AND TRIM(`game_profiles`.`publishers`) <> '' 
    AND `game_profiles`.`publishers` LIKE CONCAT('%', `publishers`.`name`, '%') 
    AND `game_profiles`.`twitch_name` = `games`.`name` 
    AND `games`.`log_date` >= SUBDATE(NOW(), INTERVAL 1 WEEK) 
    AND `games`.`log_date` <= SUBDATE(NOW(), INTERVAL 0 WEEK) 
GROUP BY `publisher_id` ORDER BY `total_views` DESC LIMIT 10; 

の下に書かれています。私が理解から

EXPLAIN result for implicit JOIN

、これは同じ結果を返すべきであるが、クエリは、MySQLのワークベンチでゆっくりと実行している私は、私はそれが実際に返すことを確認することはできませんその結果を待つことができません同じ行。しかし、EXPLAINの結果から判断すると、後者のクエリはより速く実行されるはずです。なぜこれが当てはまらないのか私がここで紛失しているものがありますか?どうもありがとうございました。

P.S.私のデータベース設計は本当に最適ではありません。これは、プロトタイプデータベースのほうが多いです。これが行われたとき、正規化は行われなかった。私は、私の質問で何が起きているのかをよりよく理解したい。ありがとうございました。

+2

あなたが書かれているSQLコードを...適切従ってくださいあなたの質問を更新してください –

+0

編集のおかげで@AnkitAgrawal – iron59

答えて

2

2番目のクエリでは暗黙的にCROSS JOINが実行されているため、クエリが永遠に実行されてしまいます。つまり、すべてのテーブルのすべての行を最初に選択し、その操作の後に結果セットをフィルタリングすることを意味します。

最初のクエリについては、

データベース設計があまり良くありません。

game_list.publishers LIKE CONCAT('%', publisher_names.publisher_name, '%'は最適ではありません。むしろリンクテーブルが必要です。

インデックスが不十分な場合は、特にgamesテーブルの列番号log_dateに欠落しているインデックスがないかどうかを確認してください。

WHERE log_date >= SUBDATE(NOW(), INTERVAL 1 WEEK) 
    AND log_date <= SUBDATE(NOW(), INTERVAL 0 WEEK) 

はところで読みやすくするためBETWEEN使用してrewittenすることができます。

WHERE log_date BETWEEN SUBDATE(NOW(), INTERVAL 1 WEEK) 
        AND SUBDATE(NOW(), INTERVAL 0 WEEK) 

LTRIM(publishers) <> ''はそれを回避しようと、sargableではありません。 publishers <> ''で十分です。

最後のINNER JOINの表gamesのグループ化もおそらく最適ではありません。そのような質問のためには、SQL Fiddleにサンプルデータを提供することが常に良いです。

しかし、すべてのサブクエリで常に1つのミスを犯しています。 INNER JOIN (SELECT x WHERE y) as Z ON z.something = a.somethingを使用します。インデックス作成のパフォーマンスが低下します。

(未確認)そのようなことになります

最適化されたクエリ:それは簡単に理解することは容易ではありませんので、非常にだらしない道(いない正しい形式)で

SELECT 
    publisher_names.id AS publisher_id 
    ,publisher_names.name AS publisher_name 
    ,SUM(view_list.views) AS total_views 
    ,SUM(view_list.channels) AS total_channels 
FROM publishers AS publisher_names 
INNER JOIN game_profiles AS game_list ON 
    twitch_name IS NOT NULL 
    AND publishers IS NOT NULL 
    AND publishers <> '' 
    AND publishers LIKE CONCAT('%', publisher_names.publisher_name, '%') 
INNER JOIN games AS view_list 
     ON log_date BETWEEN SUBDATE(NOW(), INTERVAL 1 WEEK) 
        AND SUBDATE(NOW(), INTERVAL 0 WEEK)   
      AND game_list.twitch_name = view_list.name 
WHERE publisher_names.name <> '' 
GROUP BY publisher_id 
ORDER BY total_views DESC 
+0

ええ、私のデータベース設計は本当に最適ではありません。これは、プロトタイプデータベースのほうが多いです。これが行われたとき、正規化は行われなかった。私は、私の質問で何が起きているのかをよりよく理解したい。ご回答いただきありがとうございます。私は今あなたの答えであなたが共有した情報を見ています。 – iron59

+0

私がやっていることは暗黙的なCROSS JOINであることを知らなかった。私はそれが暗黙のINNER JOINだと思った。ご回答いただきありがとうございます。 – iron59

関連する問題