クエリのEXPLAIN
プランを見ると、最適化が最適になる場所をどのように判断できますか?EXPLAINプランに基づいてMySQLクエリを最適化する方法
最初にチェックするべき点は、良いインデックスが使用されているかどうかということですが、それを超えると私はちょっと困ります。過去に試行錯誤して、ジョインが実行される順序が改善の良い原点になることがあることが時々判明しましたが、実行計画を見てどのように判断できるのでしょうか?
質問を最適化する方法をよく理解したいと思っていますが(私は非常に感謝しています)、抽象的な話ではなく具体的なケースについて議論する方が簡単です。私は現在、このいずれかで壁に頭を叩いておりますので、あなたの考えははるかに高く評価されるだろう:私は実行計画の最終行を解釈する際に修正
id select_type table type possible_keys key key_len ref rows Extra 1 SIMPLE S const PRIMARY,l,p,f4 PRIMARY 2 const 1 Using temporary 1 SIMPLE Q ref PRIMARY,S S 2 const 204 Using index 1 SIMPLE V ref PRIMARY,n,Q Q 5 const,db.Q.QID 6 Using where; Using index; Distinct 1 SIMPLE R1 ref PRIMARY,L L 154 const,db.V.VID 447 Using index; Distinct 1 SIMPLE W eq_ref PRIMARY,w PRIMARY 5 const,db.R.RID,const 1 Using where; Distinct 1 SIMPLE R2 eq_ref PRIMARY,L PRIMARY 156 const,db.W.RID,const 1 Using where; Distinct
アムを次のように:
- として主キーで完全に一致していれば、出力行ごとに1つの行だけを取り出す必要があります。
- ただし、このような出力行は、
R2
に適用されるいくつかの基準に基づいてフィルタリングされますか?
もしそうなら、私の問題は最後のステップで発生するフィルタリングにあります。条件がフィルタリングされない場合(例:WHERE `Col_1_to_3` IN (1,2,3)
)、クエリは非常に迅速に実行されます(約50ms)。ただし、条件によって選択された行(WHERE `Col_1_to_3` IN (1,2)
)が制限された場合、クエリにはかなりの時間(〜5秒)がかかります。制限が1つの一致(WHERE `Col_1_to_3` IN (1)
)の場合、オプティマイザは完全に異なる実行プランを提案します(5秒よりわずかに優れていますが、それでも50ミリ秒よりはるかに悪い)。そのテーブルで使用できるインデックスがより良いようには見えません(すでに、結果ごとに1行を返すために主キーを使用しています)。
これらすべての情報をどのように解釈する必要がありますか?そのような出力フィルタリングが最終的なテーブルに参加するため、テーブルを早期に結合し、そのような行を早期にフィルタリングするよりもかなりの労力が無駄になります。もしそうなら、実行計画の中でいつR2
が参加すべきかを決定する方法はありますか?
私はここにいっぱいで、クエリ&スキーマを含む抵抗した一方で(私は何を探すべきかを知って、本当にそうだろうとして、単に答えを告げられない)、私はそれが議論を進める必要があります理解:
SELECT DISTINCT
`Q`.`QID`
FROM
`S`
NATURAL JOIN `Q`
NATURAL JOIN `V`
NATURAL JOIN `R` AS `R1`
NATURAL JOIN `W`
JOIN `R` AS `R2` ON (
`R2`.`SID` = `S`.`SID`
AND `R2`.`RID` = `R1`.`RID`
AND `R2`.`VID` = `S`.`V_id`
AND `R2`.`Col_1_to_3` IN (1,2) -- this is where performance suffers!
)
WHERE
AND `S`.`SID` = @x
AND `W`.`WID` = @y
;
テーブルR
の定義は次のとおりです。
CREATE TABLE `R` (
`SID` smallint(6) unsigned NOT NULL,
`RID` smallint(6) unsigned NOT NULL,
`VID` varchar(50) NOT NULL DEFAULT '',
`Col_1_to_3` smallint(1) DEFAULT NULL,
`T` varchar(255) DEFAULT NULL,
PRIMARY KEY (`SID`,`RID`,`VID`),
KEY `L` (`SID`,`VID`,`Col_1_to_3`),
CONSTRAINT `R_f1` FOREIGN KEY (`SID`) REFERENCES `S` (`SID`),
CONSTRAINT `R_f2` FOREIGN KEY (`SID`, `VID`) REFERENCES `V` (`SID`, `VID`),
CONSTRAINT `R_f3` FOREIGN KEY (`SID`, `VID`, `Col_1_to_3`) REFERENCES `L` (`SID`, `VID`, `LID`)
) ENGINE=InnoDB DEFAULT CHARSET=utf8
クエリも表示されますか? –
@MarcusAdams:私は気にしませんが、何を探していますか?私はあなたが見ていることが分かっていればもっと学ぶことが多いと感じています... – eggyal
col_1_to_3を参照していますが、EXPLAIN結果にそのような列が表示されません。あなたは、それが唯一の説明であるように質問をフレーズできれば、言い換えれば質問について話している段落を削除してから、質問は必要なく、答えははいです。一般的には、クエリ、スキーマ、および説明が必要です。それ以外の場合は、推測しています。 –