MySQL5。
私は次のテーブルを持っています(多くの行でいっぱいです):
CREATE TABLE `SectorGraphs2` (
`Kind` tinyint(3) UNSIGNED NOT NULL COMMENT '1 - продюсер, 2 - жанр, 3 - регион',
`Criterion` tinyint(3) UNSIGNED NOT NULL,
`Period` tinyint(3) UNSIGNED NOT NULL,
`PeriodStart` date NOT NULL,
`SectorID` int(10) UNSIGNED NOT NULL,
`Value` float NOT NULL
) ENGINE=MyISAM DEFAULT CHARSET=utf8 COLLATE=utf8_bin;
ALTER TABLE `SectorGraphs2`
ADD UNIQUE KEY `Producer2` (`Kind`,`Criterion`,`Period`,`PeriodStart`,`SectorID`) USING BTREE,
ADD KEY `SectorID` (`SectorID`);
それから私は走ります:
EXPLAIN
SELECT SectorID, SUM(Value)
FROM SectorGraphs2
WHERE Kind = 1 AND Criterion = 7
AND Period = 1
AND PeriodStart >= ? AND PeriodStart < ? + INTERVAL 1 WEEK
GROUP BY SectorID
そしてそれは生成します:
+---+---+---+---+---+---+---+---+---+---+
| id | select_type | table | type | possible_keys | key | key_len | ref | rows | Extra |
+---+---+---+---+---+---+---+---+---+---+
| 1 | SIMPLE | SectorGraphs2 | range | Producer2,SectorID | Producer2 | 6 | NULL | 1 | Using index condition; Using temporary; Using filesort |
+---+---+---+---+---+---+---+---+---+---+
すべてのキーKind
、Criterion
、Period
、およびPeriodStart
がキーProducer2
にあるのに、なぜ一時的なものを使用するのだろうか。キーの最後のフィールドPeriodStart
を列挙するだけで計算します。 (私が学んだことによると、MySQLは、前のすべてのフィールドの値が固定されている場合、データを参照せずにキーの最後のフィールドを列挙できます。)可能であれば、一時的なものを使用せずにこれを書き換えるのを手伝ってください。
上記のコードは、いくつかの統計を保存および計算することを目的としていることに注意してください。
MySQLサーバーに過負荷をかける可能性のある重いクエリを実行しないようにする必要があります。インデックスを適切に使用し、大きな一時テーブルを回避するのに役立ちます。
ステップ1:(WHERE
)をフィルター処理して、目的の行だけを取得します。 Producer2
はそのために優れています。
ステップ2:今度はGROUP BY
。ステップ1の行はSectorIDで並べ替えられていません(PeriodStart
の「範囲」がシャッフルされたままになっているためです。これは、メモリ内のハッシュを使用するか、(おそらくRAM内で)、データを単純にパススルーします。どちらが速いかはわかりません。
MyISAMから離れる必要があります。この特定のクエリは、2つのエンジン間でインデックスが処理される方法のため、おそらくInnoDBでより高速に実行されます。
あなたのクエリは、私が話している1つの例です my index Cookbook -"インデックスは両方の範囲を処理できません(PeriodStart...
)およびGROUP BY
。
「インデックス条件の使用」が疑わしいです。これは「ICP」または「インデックス条件プッシュダウン」の同義語であり、高レベルのハンドラーにより、エンジンがインデックス作業の一部を(より効率的に)実行できるようになります。しかし、MyISAMはICP作業を行うように更新されていないと思いました。私が正しければ、これがInnoDBに移行するもう1つの理由です。それはICPの恩恵を受けます。
これが大きなテーブルの場合、クエリを高速化する別の方法(おそらく10倍)について話すことができます-- サマリーテーブル =。