Successfully reported this slideshow.
We use your LinkedIn profile and activity data to personalize ads and to show you more relevant ads. You can change your ad preferences anytime.

とあるイルカのバーボンハウス

12,663 views

Published on

2013/10/25 MySQL Casual Talks #5

  • Be the first to comment

とあるイルカのバーボンハウス

  1. 1. とあるイルカの バーボンハウス 2013/10/25 yoku0825 MySQL Casual Talks #5
  2. 2. やあ (´ ・ ω ・ `) ようこそ、バーボンハウスへ。 このDDLはサービスだから、 まず読んで落ち着いて欲しい。
  3. 3. CREATE TABLE `hogehoge`( `aa_id` bigint NOT NULL AUTO_INCREMENT, `bb_id` int unsigned NOT NULL, `key` varchar(64) NOT NULL, `cc_url` varchar(255) NOT NULL, `dd_json` text, `ee_flag` int(1) NOT NULL, `pp_date` datetime NOT NULL, `qq_date` datetime NOT NULL, PRIMARY KEY(`aa_id`), UNIQUE KEY `uidx_hogehoge_01`(`cc_url`), KEY `1`(`ee_flag`, `cc_url`, `aa_id`), KEY `2`(`cc_url', `ee_flag'), KEY `3`(`ee_flag`, `cc_url`), KEY `idx_hogehoge_01`(`key`), KEY `idx_hogehoge_02`(`pp_date`) ) ENGINE= InnoDB DEFAULT CHARSET= utf8mb4;
  4. 4. うん、「また」なんだ。済まない。 仏の顔もって言うしね、 謝って許してもらおうとも思っていない。
  5. 5. でも、このDDLを見たとき、 君は、きっと言葉では言い表せない 「ヒャッハー」みたいなものを 感じてくれたと思う。 世紀末の過ぎ去った世の中で、 そういう気持ちを忘れないで欲しい そう思って、このDDLを書いたんだ。 じゃあ、注文を聞こうか。
  6. 6. ( ゚ д ゚ ) ヒャッハー
  7. 7. 跪け! 命乞いをしろ!
  8. 8. というわけで ● ● yoku0825 とある企業のDBA ● ● ● ● オラクれない ポスグれない マイエスキューエる その正体は ● ● ● 嫁の夫 せがれの父 ぬいぐるみスキー
  9. 9. CREATE TABLE `hogehoge`( `aa_id` bigint NOT NULL AUTO_INCREMENT, `bb_id` int unsigned NOT NULL, `key` varchar(64) NOT NULL, `cc_url` varchar(255) NOT NULL, `dd_json` text, `ee_flag` int(1) NOT NULL, `pp_date` datetime NOT NULL, `qq_date` datetime NOT NULL, PRIMARY KEY(`aa_id`), UNIQUE KEY `uidx_hogehoge_01`(`cc_url`), KEY `1`(`ee_flag`, `cc_url`, `aa_id`), KEY `2`(`cc_url', `ee_flag'), KEY `3`(`ee_flag`, `cc_url`), KEY `idx_hogehoge_01`(`key`), KEY `idx_hogehoge_02`(`pp_date`) ) ENGINE= InnoDB DEFAULT CHARSET= utf8mb4;
  10. 10. ` オンラインでは INSERT が主で、 バッチで SELECT することがあります! UPDATE と DELETE は基本的に 走りません! '
  11. 11. orz ログテーブル。。 イイケドサ
  12. 12. ` 保存件数は毎月 1000 万行で、 保存期間は最低 1 年です! '
  13. 13. orz だったら型もうちょっと考えて。。
  14. 14. ` パージは月ごとのテーブルに分けて TRUNCATE しようと思うんです! '
  15. 15. Σ( ゚ д ゚ lll) 節子、それ 1 年保存やない、 11 か月保存や!
  16. 16. テーブル定義もツッコミどころ満載
  17. 17. CREATE TABLE `hogehoge`( `aa_id` bigint NOT NULL AUTO_INCREMENT, `bb_id` int unsigned NOT NULL, `key` varchar(64) NOT NULL, `cc_url` varchar(255) NOT NULL, `dd_json` text, `ee_flag` int(1) NOT NULL, `pp_date` datetime NOT NULL, `qq_date` datetime NOT NULL, PRIMARY KEY(`aa_id`), UNIQUE KEY `uidx_hogehoge_01`(`cc_url`), KEY `1`(`ee_flag`, `cc_url`, `aa_id`), KEY `2`(`cc_url', `ee_flag'), KEY `3`(`ee_flag`, `cc_url`), KEY `idx_hogehoge_01`(`key`), KEY `idx_hogehoge_02`(`pp_date`) ) ENGINE= InnoDB DEFAULT CHARSET= utf8mb4;
  18. 18. なぜサロゲートキーを SIGNED BIGINT にした
  19. 19. CREATE TABLE `hogehoge`( `aa_id` bigint NOT NULL AUTO_INCREMENT, `bb_id` int unsigned NOT NULL, `key` varchar(64) NOT NULL, `cc_url` varchar(255) NOT NULL, `dd_json` text, `ee_flag` int(1) NOT NULL, `pp_date` datetime NOT NULL, `qq_date` datetime NOT NULL, PRIMARY KEY(`aa_id`), UNIQUE KEY `uidx_hogehoge_01`(`cc_url`), KEY `1`(`ee_flag`, `cc_url`, `aa_id`), KEY `2`(`cc_url', `ee_flag'), KEY `3`(`ee_flag`, `cc_url`), KEY `idx_hogehoge_01`(`key`), KEY `idx_hogehoge_02`(`pp_date`) ) ENGINE= InnoDB DEFAULT CHARSET= utf8mb4;
  20. 20. なぜ敢えて予約語を選んだ KEY (`key`) とかギャグか
  21. 21. CREATE TABLE `hogehoge`( `aa_id` bigint NOT NULL AUTO_INCREMENT, `bb_id` int unsigned NOT NULL, `key` varchar(64) NOT NULL, `cc_url` varchar(255) NOT NULL, `dd_json` text, `ee_flag` int(1) NOT NULL, `pp_date` datetime NOT NULL, `qq_date` datetime NOT NULL, PRIMARY KEY(`aa_id`), UNIQUE KEY `uidx_hogehoge_01`(`cc_url`), KEY `1`(`ee_flag`, `cc_url`, `aa_id`), KEY `2`(`cc_url', `ee_flag'), KEY `3`(`ee_flag`, `cc_url`), KEY `idx_hogehoge_01`(`key`), KEY `idx_hogehoge_02`(`pp_date`) ) ENGINE= InnoDB DEFAULT CHARSET= utf8mb4;
  22. 22. 容量がタイトなのに 何故バイナリー文字列を CHAR 型にする
  23. 23. CREATE TABLE `hogehoge`( `aa_id` bigint NOT NULL AUTO_INCREMENT, `bb_id` int unsigned NOT NULL, `key` varchar(64) NOT NULL, `cc_url` varchar(255) NOT NULL, `dd_json` text, `ee_flag` int(1) NOT NULL, `pp_date` datetime NOT NULL, `qq_date` datetime NOT NULL, PRIMARY KEY(`aa_id`), UNIQUE KEY `uidx_hogehoge_01`(`cc_url`), KEY `1`(`ee_flag`, `cc_url`, `aa_id`), KEY `2`(`cc_url', `ee_flag'), KEY `3`(`ee_flag`, `cc_url`), KEY `idx_hogehoge_01`(`key`), KEY `idx_hogehoge_02`(`pp_date`) ) ENGINE= InnoDB DEFAULT CHARSET= utf8mb4;
  24. 24. int(1) は 1 バイト INT じゃない 1 バイト INT は TINYINT だ
  25. 25. CREATE TABLE `hogehoge`( `aa_id` bigint NOT NULL AUTO_INCREMENT, `bb_id` int unsigned NOT NULL, `key` varchar(64) NOT NULL, `cc_url` varchar(255) NOT NULL, `dd_json` text, `ee_flag` int(1) NOT NULL, `pp_date` datetime NOT NULL, `qq_date` datetime NOT NULL, PRIMARY KEY(`aa_id`), UNIQUE KEY `uidx_hogehoge_01`(`cc_url`), KEY `1`(`ee_flag`, `cc_url`, `aa_id`), KEY `2`(`cc_url', `ee_flag'), KEY `3`(`ee_flag`, `cc_url`), KEY `idx_hogehoge_01`(`key`), KEY `idx_hogehoge_02`(`pp_date`) ) ENGINE= InnoDB DEFAULT CHARSET= utf8mb4;
  26. 26. 5.5 なら DATETIME は 8 バイトだが TIMESTAMP は 4 バイトだ
  27. 27. CREATE TABLE `hogehoge`( `aa_id` bigint NOT NULL AUTO_INCREMENT, `bb_id` int unsigned NOT NULL, `key` varchar(64) NOT NULL, `cc_url` varchar(255) NOT NULL, `dd_json` text, `ee_flag` int(1) NOT NULL, `pp_date` datetime NOT NULL, `qq_date` datetime NOT NULL, PRIMARY KEY(`aa_id`), UNIQUE KEY `uidx_hogehoge_01`(`cc_url`), KEY `1`(`ee_flag`, `cc_url`, `aa_id`), KEY `2`(`cc_url', `ee_flag'), KEY `3`(`ee_flag`, `cc_url`), KEY `idx_hogehoge_01`(`key`), KEY `idx_hogehoge_02`(`pp_date`) ) ENGINE= InnoDB DEFAULT CHARSET= utf8mb4;
  28. 28. 何故その名前にしたのか 俺の目を見て言ってみろ
  29. 29. CREATE TABLE `hogehoge`( `aa_id` bigint NOT NULL AUTO_INCREMENT, `bb_id` int unsigned NOT NULL, `key` varchar(64) NOT NULL, `cc_url` varchar(255) NOT NULL, `dd_json` text, `ee_flag` int(1) NOT NULL, `pp_date` datetime NOT NULL, `qq_date` datetime NOT NULL, PRIMARY KEY(`aa_id`), UNIQUE KEY `uidx_hogehoge_01`(`cc_url`), KEY `1`(`ee_flag`, `cc_url`, `aa_id`), KEY `2`(`cc_url', `ee_flag'), KEY `3`(`ee_flag`, `cc_url`), KEY `idx_hogehoge_01`(`key`), KEY `idx_hogehoge_02`(`pp_date`) ) ENGINE= InnoDB DEFAULT CHARSET= utf8mb4;
  30. 30. 情報量が全くない名前をつけるな
  31. 31. CREATE TABLE `hogehoge`( `aa_id` bigint NOT NULL AUTO_INCREMENT, `bb_id` int unsigned NOT NULL, `key` varchar(64) NOT NULL, `cc_url` varchar(255) NOT NULL, `dd_json` text, `ee_flag` int(1) NOT NULL, `pp_date` datetime NOT NULL, `qq_date` datetime NOT NULL, PRIMARY KEY(`aa_id`), UNIQUE KEY `uidx_hogehoge_01`(`cc_url`), KEY `1`(`ee_flag`, `cc_url`, `aa_id`), KEY `2`(`cc_url', `ee_flag'), KEY `3`(`ee_flag`, `cc_url`), KEY `idx_hogehoge_01`(`key`), KEY `idx_hogehoge_02`(`pp_date`) ) ENGINE= InnoDB DEFAULT CHARSET= utf8mb4;
  32. 32. aa_id はクラスタードインデックスだから 末尾につける必要はない `3` と重複してる
  33. 33. CREATE TABLE `hogehoge`( `aa_id` bigint NOT NULL AUTO_INCREMENT, `bb_id` int unsigned NOT NULL, `key` varchar(64) NOT NULL, `cc_url` varchar(255) NOT NULL, `dd_json` text, `ee_flag` int(1) NOT NULL, `pp_date` datetime NOT NULL, `qq_date` datetime NOT NULL, PRIMARY KEY(`aa_id`), UNIQUE KEY `uidx_hogehoge_01`(`cc_url`), KEY `1`(`ee_flag`, `cc_url`, `aa_id`), KEY `2`(`cc_url', `ee_flag'), KEY `3`(`ee_flag`, `cc_url`), KEY `idx_hogehoge_01`(`key`), KEY `idx_hogehoge_02`(`pp_date`) ) ENGINE= InnoDB DEFAULT CHARSET= utf8mb4;
  34. 34. `2` と `3` も微妙だ ORDER BY 狙いだから 重複じゃないっていうにしては cc_url はユニークキーだ
  35. 35. orz
  36. 36. 怖ろしいDDLしてるだろ。 ウソみたいだろ。 SQLレビュー通ってるんだぜ、 それで。
  37. 37. orz
  38. 38. ` じゃあどうしろと? '
  39. 39. CREATE TABLE `hogehoge`( `aa_id` int unsigned NOT NULL AUTO_INCREMENT, `bb_id` int unsigned NOT NULL, `ff_key` varbinary(64) NOT NULL, `cc_url` varbinary(255) NOT NULL, `dd_json` blob, `ee_flag` tinyint NOT NULL, `pp_date` timestamp NOT NULL, `qq_date` timestamp NOT NULL, PRIMARY KEY(`aa_id`, pp_date), UNIQUE KEY `idx_ccurl`(`cc_url`), KEY `idx_eeflag_ccurl_aaid` (`ee_flag`, `cc_url`, `aa_id`), KEY `idx_ccurl_eeflag`(`cc_url', `ee_flag'), KEY `idx_eeflag_ccurl`(`ee_flag`, `cc_url`), KEY `idx_ffkey`(`ff_key`), KEY `idx_ppdate`(`pp_date`) ) ENGINE= InnoDB ROW_FORMAT= COMPRESSED DEFAULT CHARSET= utf8mb4 PARTITION BY LIST(..) ..;
  40. 40. 容量節約第一
  41. 41. ただし binary 型は Java でフェッチすると java.lang.String じゃなくて byte[] で戻るらしい
  42. 42. ガッツで何とかしてもらった
  43. 43. LIST パーティショニングで 24 分割 { 偶数年 | 奇数年 } * 12 ヶ月
  44. 44. パーティショニング定義が超きたない
  45. 45. そんなにオーバーヘッドなかったから いいことにする
  46. 46. と、自分に言い聞かせている
  47. 47. インデックスの名前は基本、カラム名 ALTER TABLE .. DROP KEY の KEY キーワードをつけ忘れると悲惨なので 接頭辞 idx はつけることにした最近
  48. 48. mysql> explain -> SELECT * -> FROM fugafuga -> WHERE aa_id = xx -> AND bb_status = xx -> AND cc_id > xx -> AND dd_date >= DATE_SUB(CURRENT_DATE, INTERVAL 30 DAY) -> ORDER BY aa_id descG *************************** 1. row *************************** id: 1 select_type: SIMPLE table: fugafuga type: range possible_keys: uidx_fugafuga, idx_fugafuga_01, idx_fugafuga_02, idx_fugafuga_03 key: idx_fugafuga_01 key_len: 4 ref: NULL rows: 2 Extra: Using where; Using filesort 1 row in set (0.00 sec)
  49. 49. EXPLAIN 取った時に見にくい SHOW CREATE TABLE とセットで見るけど、 10 個以上キーがあるとめげる
  50. 50. USE INDEX 書く時も、 WHERE を狙ってるのか ORDER BY を狙ってるのかよく判らない
  51. 51. mysql> explain -> SELECT * -> FROM fugafuga -> WHERE aa_id = xx -> AND bb_status = xx -> AND cc_id > xx -> AND dd_date >= DATE_SUB(CURRENT_DATE, INTERVAL 30 DAY) -> ORDER BY aa_id descG *************************** 1. row *************************** id: 1 select_type: SIMPLE table: fugafuga type: range possible_keys: uni_aaid_eeid_dddate, idx_dddate_bbstatus_ccid, idx_aaid_bbstatus_ccid_dddate_ffid, idx_ccid_bbstatus_dddate key: idx_dddate_bbstatus_ccid key_len: 4 ref: NULL rows: 113055 Extra: Using where; Using filesort 1 row in set (0.00 sec)
  52. 52. 名前から型が推測できると更にすてき dd_date は DATETIME 型か TIMESTAMP 型だろう で、 key_len が 4 だから TIMESTAMP 型で しかも先頭の dd_date 部分しか 効いてないね RANGE スキャンだもんね
  53. 53. mysql> explain -> SELECT * -> FROM fugafuga USE INDEX(idx_aaid_bbstatus_ccid_dddate_ffid) -> WHERE aa_id = xx -> AND bb_status = xx -> AND cc_id > xx -> AND dd_date >= DATE_SUB(CURRENT_DATE, INTERVAL 30 DAY) -> ORDER BY aa_id descG *************************** 1. row *************************** id: 1 select_type: SIMPLE table: fugafuga type: range possible_keys: uni_aaid_eeid_dddate, idx_dddate_bbstatus_ccid, idx_aaid_bbstatus_ccid_dddate_ffid, idx_ccid_bbstatus_dddate key: idx_aaid_bbstatus_ccid_dddate_ffid key_len: 5 ref: NULL rows: 509 Extra: Using where; Using filesort 1 row in set (0.00 sec)
  54. 54. どこ狙ったのかが SQL だけで伝わる アプリのコードに直接触ら ( れ ) ない わたしにとってこれ意思疎通が超捗る
  55. 55. コードだけで会話する必要はないけど、 コードで判りあうことも必要
  56. 56. とはいえ、 update_date とか フレームワークが自動で生成してるの 知りませんでした orz
  57. 57. 会話できるようになりたい orz
  58. 58. なお、このスライドは フィクションであり、 実在するDDLとは 一切関係がありません
  59. 59. とかだったら、 いいんですけどね! :)
  60. 60. ご清聴ありがとうございました

×