範囲が含まれる場合は、最初にカーディナリティの高い列でインデックスを作成します
次のテーブルを考えてみましょう。
CREATE TABLE `files` ( `did` int(10) unsigned NOT NULL DEFAULT '0', `filename` varbinary(200) NOT NULL, `ext` varbinary(5) DEFAULT NULL, `fsize` double DEFAULT NULL, `filetime` datetime DEFAULT NULL, PRIMARY KEY (`did`,`filename`), KEY `fe` (`filetime`,`ext`), -- This? KEY `ef` (`ext`,`filetime`) -- or This? ) ENGINE=InnoDB DEFAULT CHARSET=utf8 ;
100 万行、filetime のカーディナリティが高く、ext のカーディナリティが低い、 fe と ef のどちらのインデックスがより有利であるかという疑問が生じます。
Force Index と EXPLAIN による分析
FORCE INDEX を使用して両方のインデックスをテストすると、明らかな違いが明らかになりますパフォーマンス:
-- Forcing the range on filetime first mysql> EXPLAIN SELECT COUNT(*), AVG(fsize) FROM files FORCE INDEX(fe) WHERE ext = 'gif' AND filetime >= '2015-01-01' AND filetime < '2015-01-01' + INTERVAL 1 MONTH;
-- Forcing the low-cardinality ext first mysql> EXPLAIN SELECT COUNT(*), AVG(fsize) FROM files FORCE INDEX(ef) WHERE ext = 'gif' AND filetime >= '2015-01-01' AND filetime < '2015-01-01' + INTERVAL 1 MONTH;
EXPLAIN 出力は、ef が
オプティマイザー トレースによる分析
オプティマイザー トレースは ef:
"potential_range_indices": [ ... { "index": "fe", "usable": true, ... }, { "index": "ef", "usable": true, ... } ], "analyzing_range_alternatives": { "range_scan_alternatives": [ { "index": "fe", "ranges": [ "2015-01-01 00:00:00 <= filetime < 2015-02-01 00:00:00" ], "cost": 20022, -- Higher cost }, { "index": "ef", "ranges": [ "gif <= ext <= gif AND 2015-01-01 00:00:00 <= filetime < 2015-02-01 00:00:00" ], "cost": 646.61, -- Lower cost } ], }
結論
分析に基づくと、次のようになります。複数のインデックス付き列を含む範囲クエリを処理する場合、列の順序は次のとおりである必要があることを明確にします。 be:以上が範囲クエリを使用する複数列インデックスでは、カーディナリティの高い列を最初に置く必要がありますか?の詳細内容です。詳細については、PHP 中国語 Web サイトの他の関連記事を参照してください。