調べたことメモ
- distinct
指定した列の重複を除くキーワード。データの並べ替えが必要なので遅いらしい。
30万レコードくらいのデータで試してみる。
select distinct user_id, content from data; 299990 rows in set (7.82 sec) select user_id, content from data; 300000 rows in set (1.21 sec)
必要なときだけ理解して使いなさいとのこと(by 初めてのSQL)
- whereとhaving
where節にはデータベースのデータに適用されるフィルタを、havingには集約されたデータに適用されるフィルタを記述する。whereはグループ化の前に評価される。
select user_id, count(user_id) as count from oneword_data where user_id > 15000 group by user_id having count > 30 ;
- group by
カラム名ではなく式を指定することも可能
select user_id%10, count(user_id) num from user_data group by user_id%10 ;
- like
検索式を使って条件をつくる。
testで始まる文字列を探す(testのみでもok)
select content from oneword_data where content like 'test%' ;
test+任意の一字の文字列を探す。
select content from oneword_data where content like 'test_' ;
- regexp
正規表現で検索する。
testで始まる文字列を探す(testのみでもok)
select content from oneword_data where content regexp 'test.*' ;
test+任意の一字の文字列を探す
select content from oneword_data where content regexp 'test.' ;
- likeとregexpの速度
どっちが速いか?
select content from oneword_data where content regexp '^test1.*0$'; 13333 rows in set (1.12 sec) select content from oneword_data where content like 'test1%0'; 13333 rows in set (0.59 sec)
likeのほうが倍近く速い。
これだとどうだ?
select content from oneword_data where content regexp '^test.*0$'; 30000 rows in set (0.95 sec) select content from oneword_data where content like 'test%0'; 30000 rows in set (0.68 sec)
正規表現は速くなったが、それでもまだlikeのほうが速い
さらに試してみる。
select content from oneword_data where content regexp '^test1.2.*'; 13330 rows in set (1.19 sec) select content from oneword_data where content like 'test1_2%'; 13330 rows in set (0.58 sec)
やっぱりlikeのほうが速い。
実装がわからないのでアレだが、likeでできることならlikeでSQLを書いたほうがよさげ。
- in
サブクエリの結果が多いとメチャ遅い。
select * from oneword_data where user_id in ( select user_id from oneword_data where user_id > 15000 ) ; 147880 rows in set (6.69 sec) select * from oneword_data where user_id > 15000 ; 147880 rows in set (1.23 sec)
user_id in(1111, 2222)だったらuser_id=1111 OR user_id=2222
に内部変換しているのだろう。そう考えると納得。
- filesort
MySQLでEXPLAIN SELECT...を実行するとExtraフィールドでよく見かける「Using filesort」という文字列。Filesortって一体なんだろう?と思ったことはないだろうか。単刀直入に言ってFilesortの正体はクイックソートである。
クエリにORDER BYが含まれる場合、MySQLはある程度の大きさまでは全てメモリ内でクイックソートを処理する。ある程度の大きさとはsort_buffer_sizeであり、これはセッションごとに変更可能である。ソートに必要なメモリがsort_buffer_sizeより大きくなると、テンポラリファイル(テンポラリテーブルではない)が作成され、メモリとファイルを併用してクイックソートが実行される。
引用元:http://nippondanji.blogspot.com/2009/03/using-filesort.html
filesortが発生しないようなSQLか要チェックということですね。
まとめ
-
- むやみにdistinctを使わない
- havingには集約結果のフィルタリング条件を
- likeとregexpではlikeのほうが速い
- inでたくさんの結果を含むようなサブクエリは避けるべき
- explain select〜でSQLの実行計画を調べるべき