を使用すると、私は起動しようとしているクエリです:一時的な使用によるMySQLソート。ここでfilesortレコード
:ここがcreatives
テーブル構造である:ここで
SELECT c.creative_id, c.creative_title, c.creative_image_name, c.gravity, c.ad_strength
FROM creatives AS c
INNER JOIN term_relationships AS tr ON c.creative_id = tr.creative_id
WHERE tr.term_id
IN (14, 1, 50, 76, 104)
GROUP BY c.creative_id
HAVING COUNT(tr.term_id) =5
ORDER BY c.gravity ASC
LIMIT 30;
は、どのようなこのクエリの出力のEXPLAIN
です
CREATE TABLE `creatives` (
`creative_id` bigint(20) unsigned NOT NULL AUTO_INCREMENT,
`scraper_id` bigint(20) unsigned DEFAULT NULL,
`creative_title` varchar(255) NOT NULL,
`creative_image_name` varchar(255) DEFAULT NULL,
`image_attrib` varchar(12) DEFAULT NULL,
`original_image_name` varchar(255) DEFAULT NULL,
`creative_subtext` varchar(255) DEFAULT NULL,
`dest_url` varchar(2083) NOT NULL,
`lp_url` varchar(2083) NOT NULL,
`lp_image_name` varchar(255) DEFAULT NULL,
`lp_image_flag` tinyint(1) unsigned NOT NULL DEFAULT '0',
`creative_first_seen` date NOT NULL,
`creative_last_seen` date NOT NULL,
`daily_ad_count` int(5) unsigned NOT NULL,
`ad_strength` int(11) unsigned NOT NULL,
`prev_ad_strength` int(11) unsigned DEFAULT NULL,
`gravity` int(11) unsigned DEFAULT NULL,
PRIMARY KEY (`creative_id`),
KEY `gravity` (`gravity`)
) ENGINE=InnoDB AUTO_INCREMENT=173037591 DEFAULT CHARSET=utf8
私は両者を起動するとUsing temporary; using filesort
が心配です他の列にはGROUP BY
とORDER BY
があります。 ORDER BY
を削除した場合、一時ファイルとファイル・セットがなくなり、クエリが本当に速く実行されます。
私は理解できませんが、なぜ一時的なテーブルが必要なのですか?c.gravity
でフィルターを並べ替えてから、結果テーブルとグループをグループ化してHAVING
節に従ってください。フィルタリングされたテーブルは、グループ化してフィルタを適用した後でも重力値が変更されないままであるため、c.gravity
で正しくソートされます。私が試した何
:ORDER BY
なし
選択したすべてのもの、サブクエリの中に包み、
creatives
テーブルの上に再び参加しました - 一時的な、filesortレコードを使用して同じ結果を、ゆっくりとが
FORCE USE INDEX FOR ORDER BY (gravity)
を追加しようとしましたし、それは何も変わらない。EXPLAIN
と実行時間は変わりません。
UPDATE:質問は@Rickによって回答されており、それは本当に非常に速く、彼相関サブクエリではなくGROUP BY
を使用しています。
そして、新しく作成されたインデックスを持つSHOW CREATE TABLE term_relationships
の出力:
そして@Rickへの1つの以上の質問:なぜ私はここにクエリのEXPLAIN
出力を追加していますc3
という外部クエリが必要ですか? creatives
に他の列の値を取得し、レコードを重力順に並べ替えるだけの方法があります。しかし、彼らはすでに、内側のクエリでソートされ、我々は簡単にそれを作るc1
に欠けている列を追加することができます
SELECT c1.creative_id,c1.creative_title,c1.creative_image_name,c1.gravity, c1.ad_strength
FROM creatives AS c1
WHERE
(SELECT COUNT(*)
FROM term_relationships
WHERE c1.creative_id = creative_id
AND term_id IN (14, 1, 50, 76, 104)
) = 5
ORDER BY c1.gravity ASC
LIMIT 30;
が正しい私の理解ですか私はあなたのクエリで何かが足りないのですか?
( 'c3'について)' c3'を指定しないと、 'creative_id'だけがtmpテーブル内を迂回します。 'c3'では、たくさんの列が巡回されます。 'LIMIT'(30)と' LIMITing'の前の行数に大きな違いがある場合、パフォーマンスの差が顕著になる可能性があります。 –