MySQL

9,651 views

Published on

MySQL

  1. 1. 俺のSQLがこんなに 遅いわけがない id:paulownia twitter : @nullpon
  2. 2. 4月
  3. 3. サイバーエージェント エンジニアブログに 投稿された あるエントリが話題に
  4. 4. Redis それは危険なほどの スピード
  5. 5. MySQLの2倍速い!
  6. 6. はてなブックマーク でも注目
  7. 7. 注)はてブユーザのイメージ画像
  8. 8. •HASH index 使ってて range search やってるのに MySQL 遅いとか言ってて 大丈夫なの? •INDEX USING BTREE に したらいいんじゃ •ブックマークコメントで マサカリが飛び交っていると聞いて •タイトルがカッコイイw はてブのコメント
  9. 9. というわけで 検証してみた
  10. 10. 1. Hashインデックス意味ないの? 2. B-Treeならば速い? 3. 何故Redisは2倍も速いのか? 4. MySQLで危険なスピードに挑む
  11. 11. Hash インデックス 意味ないの? ①
  12. 12. 比較してみる
  13. 13. write read Hash インデックス 14,016ms 755,127ms インデックス なし 13,711ms 736,358ms
  14. 14. ほぼ同じ…
  15. 15. explainしてみる
  16. 16. explain select count(point) from ranking where point > ( select point from ranking where id = 'user3939' )G
  17. 17. *************************** 1. row ************* id: 1 select_type: PRIMARY table: ranking type: ALL possible_keys: point key: NULL key_len: NULL ref: NULL rows: 100000 Extra: Using where *************************** 2. row ************* id: 2 select_type: SUBQUERY table: ranking type: const possible_keys: PRIMARY
  18. 18. テーブルフルスキャン してる…
  19. 19. where句が < , > , betweenのとき Hashインデックスは使えません…
  20. 20. Hashインデックス 意味なし!
  21. 21. B-Treeインデックス ならば速い? ②
  22. 22. 比較してみる
  23. 23. write read B-Tree インデックス 13,734ms 1,398,129ms インデックス なし 13,711ms 736,358ms
  24. 24. B-Tree遅ぇ
  25. 25. 何故?
  26. 26. B-Treeが有効な理由 •Index Range Scan •Covering Index
  27. 27. Index Range Scan •範囲検索を高速化する •B-Treeインデックスはソート済み •読み込みレコード件数が減るので 高速
  28. 28. しかし 多くのレコードをreadする場合、 インデックス読みの込みの分、 むしろ遅くなる。
  29. 29. Covering Index •インデックスに格納された値のみで 処理し、テーブルを読まない •MySQL高速化の常套手段
  30. 30. しかし Memoryエンジンでは Covering Indexが使えない
  31. 31. というか、RDBのIndexは 少数のレコードを高速に検索するためのものなので 今回のようにテーブルのほとんどのデータを読む 場合には不向き
  32. 32. インデックスが有効なのは select範囲がテーブルの 30%ぐらいまで
  33. 33. B-Treeインデックス 意味なし!
  34. 34. 何故Redisは MySQLの 2倍速い? ③
  35. 35. 読み込み件数の差で 説明できる
  36. 36. ベンチマークでやってる事 •N 件のデータに対して(N > 1) •1以上 N 以下のポイントをランダムに振り、 •M ポイントより大きいデータ件数を countする(1 < M < N)
  37. 37. N = 100,000 Redis ソート済みセット  読み取りレコード件数(の期待値):50,000件 MySQL テーブルフルスキャン  読み取りレコード件数:100,000件 ベンチマークでやってる事
  38. 38. RedisのRead件数は MySQLの半分
  39. 39. だから 2倍速い
  40. 40. ④ MySQLで 危険なスピードに チャレンジ
  41. 41. インデックスを使わず、 Read件数を減らせれば 高速化できそうな気がする
  42. 42. そんな都合のいい方法あるの? あります
  43. 43. パーティショニング (Partitioning)
  44. 44. pointの値でテーブルを分割し 範囲内のパーティションのみ スキャン
  45. 45. パーティションの刈り込み (Patition Pruning)
  46. 46. CREATE TABLE ranking ( id VARCHAR(12) NOT NULL, point INT NOT NULL, PRIMARY KEY (id, point) USING BTREE ) ENGINE=memory PARTITION BY RANGE COLUMNS(point) ( PARTITION p0 VALUES LESS THAN (10000), PARTITION p1 VALUES LESS THAN (20000), PARTITION p2 VALUES LESS THAN (30000), PARTITION p3 VALUES LESS THAN (40000), PARTITION p4 VALUES LESS THAN (50000), PARTITION p5 VALUES LESS THAN (60000), PARTITION p6 VALUES LESS THAN (70000), PARTITION p7 VALUES LESS THAN (80000), PARTITION p8 VALUES LESS THAN (90000), PARTITION p9 VALUES LESS THAN MAXVALUE );
  47. 47. 10のパーティションに分割 平均45%のレコード読み込みを スキップできる Redisに匹敵する速度が 出るはず!
  48. 48. 実験してみた
  49. 49. MacBook Air OSX 10.7.3 Core i5 1.7GHz 4GB Mem Redis 2.4.4 MySQL 5.5.15
  50. 50. write read Redis SortedSet 12,483ms 460,709ms MySQL Partition Pruning 13,841ms 598,233ms MySQL Table Full Scan 13,711ms 736,358ms
  51. 51. orz
  52. 52. Table Full Scanより速いものの 思ったほど速くならなかった →パーティション刈り込みには最 適化の余地あり? CAブログの結果と比べると Redisはほぼ同じだが、 MySQLフルスキャンがかなり速い →MySQLは環境依存が大きい? 2倍速い理由が Read件数で説明できなくなったし →てへぺろ
  53. 53. Redis速ぇ…
  54. 54. おしまい

×