MySQLでdatetime型にもインデックスを使用
ログ関連のデータを格納するテーブルがあり、集計を行う際に非常に時間がかかった。レコード数は1億ほどあったので、これはもう仕方がないんじゃないかと思ったんだけど他者が作成したテーブルで3億ほどレコード数があるのに高速で動いていた。色々調べてみた結果のメモ。
違いを調べてみた結果
両者のテーブル構造やインデックス構造を確認したところ、高速で動く方はdatetime型のカラムにインデックスが貼られていた。またパーティショニングされていた。
パーティショニング
パーティショニングというのは初めて聞いたので調べてみたところ、テーブルを分割して高速化を図る機能みたい。ただ、パーティショニングは途中(2016年とか)で切れていたので今回はあまり関係なさそう。
https://liginc.co.jp/programmer/archives/3832
datetime型にインデックス
datetime型にインデックスを張ってもフルスキャンされると思い込んでいたがどうやら違うみたい。試しに以下テーブルを作成し400万ほどランダムなデータを入れた。created_dataの範囲は2014-01-01から2014-06-30まで。
mysql> show columns from item; +--------------+------------------+------+-----+---------+----------------+ | Field | Type | Null | Key | Default | Extra | +--------------+------------------+------+-----+---------+----------------+ | id | int(11) | NO | PRI | NULL | auto_increment | | key | varchar(30) | YES | | NULL | | | point | int(10) unsigned | YES | | NULL | | | created_date | datetime | YES | MUL | NULL | | +--------------+------------------+------+-----+---------+----------------+ #インデックスなし SELECT * FROM item WHERE created_date BETWEEN '2014-01-01 00:00:00' AND '2014-01-01 23:59:59' #実行結果1.004 秒 #インデックスあり SELECT * FROM item WHERE created_date BETWEEN '2014-01-01 00:00:00' AND '2014-01-01 23:59:59' #実行結果0.044 秒
EXPLAINで調べたところtypeはrangeになっていたのでインデックスはきいていることが確認でき、20倍ほど速度が改善された。
注意点
大量データに後からインデックスを張る場合はサイトはメンテナンスモードにしてMySQLにクエリが入らない状態にして行った方が良さそう。テーブルロックがかかるようで更新ができないし、killで強制終了した場合はデータが破損する可能性がある。
関連記事
-
-
MySQLでパターンマッチの逆
LIKE検索の逆ってなったのでメモ。 NOT LIKE '%あああ%' が正解み ...
-
-
MySQLで開始から終了日付内を調べたいとき
等号不等号でもできるけど、BETWEENというのがよさそう。 ■参考サイト ht ...
-
-
SortableJSを使ってデータの並べ替え&保存
あるシステムを拝見した際にtableタグ内に並んでいる項目をドラッグ&ド ...
-
-
お名前.comの共用サーバー(SD)にphpmyadminを入れる
公式で書いてあるやつは3.4.2だけど、もうちょっと新しいバージョンを入れたかっ ...
-
-
MySQLで同一サーバーの異なるDB内のテーブルをJOINする
同一のMySQLサーバーでdb1データベースのtable1テーブルと、db2デー ...
-
-
MySQLでtime型データの減算と条件検索
MySQLでtime型データからint型データの減算を行い、減算後のデータを検索 ...
-
-
エックスサーバーでMySQLのサイズに注意
エックスサーバーで自動更新のログをMySQLに保存するようなシステムを動かしてい ...
-
-
MySQLでIPを整数値としてカラムに格納する
MySQLでIPを整数値としてカラムに格納しているケースがあった。今までIPが必 ...
-
-
MySQLのREGEXPで半角記号を検索したい場合
MySQLのREGEXPで半角記号を検索したい場合 \\を付けてエスケープしない ...
-
-
MySQLiでDELETE文
MySQLiでDELETE文 ■ソース $mysqli = new mysqli ...