0
とあるイルカの
バーボンハウス
2013/10/25
yoku0825
MySQL Casual Talks #5
やあ (´ ・ ω ・ `)
ようこそ、バーボンハウスへ。
このDDLはサービスだから、
まず読んで落ち着いて欲しい。
CREATE TABLE `hogehoge`(
`aa_id`
bigint NOT NULL AUTO_INCREMENT,
`bb_id`
int unsigned NOT NULL,
`key`
varchar(64) NOT NULL...
うん、「また」なんだ。済まない。
仏の顔もって言うしね、
謝って許してもらおうとも思っていない。
でも、このDDLを見たとき、
君は、きっと言葉では言い表せない
「ヒャッハー」みたいなものを
感じてくれたと思う。
世紀末の過ぎ去った世の中で、
そういう気持ちを忘れないで欲しい
そう思って、このDDLを書いたんだ。
じゃあ、注文を聞こうか。
( ゚ д ゚ ) ヒャッハー
跪け!
命乞いをしろ!
というわけで
●
●

yoku0825
とある企業のDBA
●
●
●

●

オラクれない
ポスグれない
マイエスキューエる

その正体は
●
●
●

嫁の夫
せがれの父
ぬいぐるみスキー
CREATE TABLE `hogehoge`(
`aa_id`
bigint NOT NULL AUTO_INCREMENT,
`bb_id`
int unsigned NOT NULL,
`key`
varchar(64) NOT NULL...
` オンラインでは INSERT が主で、
バッチで SELECT することがあります!
UPDATE と DELETE は基本的に
走りません! '
orz
ログテーブル。。
イイケドサ
` 保存件数は毎月 1000 万行で、
保存期間は最低 1 年です! '
orz
だったら型もうちょっと考えて。。
` パージは月ごとのテーブルに分けて
TRUNCATE しようと思うんです! '
Σ( ゚ д ゚ lll)
節子、それ 1 年保存やない、
11 か月保存や!
テーブル定義もツッコミどころ満載
CREATE TABLE `hogehoge`(
`aa_id`
bigint NOT NULL AUTO_INCREMENT,
`bb_id`
int unsigned NOT NULL,
`key`
varchar(64) NOT NULL...
なぜサロゲートキーを
SIGNED BIGINT にした
CREATE TABLE `hogehoge`(
`aa_id`
bigint NOT NULL AUTO_INCREMENT,
`bb_id`
int unsigned NOT NULL,
`key`
varchar(64) NOT NULL...
なぜ敢えて予約語を選んだ
KEY (`key`) とかギャグか
CREATE TABLE `hogehoge`(
`aa_id`
bigint NOT NULL AUTO_INCREMENT,
`bb_id`
int unsigned NOT NULL,
`key`
varchar(64) NOT NULL...
容量がタイトなのに
何故バイナリー文字列を CHAR 型にする
CREATE TABLE `hogehoge`(
`aa_id`
bigint NOT NULL AUTO_INCREMENT,
`bb_id`
int unsigned NOT NULL,
`key`
varchar(64) NOT NULL...
int(1) は 1 バイト INT じゃない
1 バイト INT は TINYINT だ
CREATE TABLE `hogehoge`(
`aa_id`
bigint NOT NULL AUTO_INCREMENT,
`bb_id`
int unsigned NOT NULL,
`key`
varchar(64) NOT NULL...
5.5 なら DATETIME は 8 バイトだが
TIMESTAMP は 4 バイトだ
CREATE TABLE `hogehoge`(
`aa_id`
bigint NOT NULL AUTO_INCREMENT,
`bb_id`
int unsigned NOT NULL,
`key`
varchar(64) NOT NULL...
何故その名前にしたのか
俺の目を見て言ってみろ
CREATE TABLE `hogehoge`(
`aa_id`
bigint NOT NULL AUTO_INCREMENT,
`bb_id`
int unsigned NOT NULL,
`key`
varchar(64) NOT NULL...
情報量が全くない名前をつけるな
CREATE TABLE `hogehoge`(
`aa_id`
bigint NOT NULL AUTO_INCREMENT,
`bb_id`
int unsigned NOT NULL,
`key`
varchar(64) NOT NULL...
aa_id はクラスタードインデックスだから
末尾につける必要はない
`3` と重複してる
CREATE TABLE `hogehoge`(
`aa_id`
bigint NOT NULL AUTO_INCREMENT,
`bb_id`
int unsigned NOT NULL,
`key`
varchar(64) NOT NULL...
`2` と `3` も微妙だ
ORDER BY 狙いだから
重複じゃないっていうにしては
cc_url はユニークキーだ
orz
怖ろしいDDLしてるだろ。
ウソみたいだろ。
SQLレビュー通ってるんだぜ、
それで。
orz
` じゃあどうしろと? '
CREATE TABLE `hogehoge`(
`aa_id`
int unsigned NOT NULL AUTO_INCREMENT,
`bb_id`
int unsigned NOT NULL,
`ff_key`
varbinary(6...
容量節約第一
ただし binary 型は Java でフェッチすると
java.lang.String じゃなくて
byte[] で戻るらしい
ガッツで何とかしてもらった
LIST パーティショニングで 24 分割
{ 偶数年 | 奇数年 } * 12 ヶ月
パーティショニング定義が超きたない
そんなにオーバーヘッドなかったから
いいことにする
と、自分に言い聞かせている
インデックスの名前は基本、カラム名
ALTER TABLE .. DROP KEY の
KEY キーワードをつけ忘れると悲惨なので
接頭辞 idx はつけることにした最近
mysql> explain
-> SELECT *
-> FROM fugafuga
-> WHERE aa_id = xx
-> AND bb_status = xx
-> AND cc_id > xx
-> AND dd_date >= ...
EXPLAIN 取った時に見にくい
SHOW CREATE TABLE とセットで見るけど、
10 個以上キーがあるとめげる
USE INDEX 書く時も、
WHERE を狙ってるのか
ORDER BY を狙ってるのかよく判らない
mysql> explain
-> SELECT *
-> FROM fugafuga
-> WHERE aa_id = xx
->
AND bb_status = xx
->
AND cc_id > xx
->
AND dd_date >= ...
名前から型が推測できると更にすてき
dd_date は
DATETIME 型か TIMESTAMP 型だろう
で、 key_len が 4 だから TIMESTAMP 型で
しかも先頭の dd_date 部分しか
効いてないね RANGE スキ...
mysql> explain
-> SELECT *
-> FROM fugafuga USE INDEX(idx_aaid_bbstatus_ccid_dddate_ffid)
-> WHERE aa_id = xx
->
AND bb_st...
どこ狙ったのかが SQL だけで伝わる
アプリのコードに直接触ら ( れ ) ない
わたしにとってこれ意思疎通が超捗る
コードだけで会話する必要はないけど、
コードで判りあうことも必要
とはいえ、 update_date とか
フレームワークが自動で生成してるの
知りませんでした orz
会話できるようになりたい orz
なお、このスライドは
フィクションであり、
実在するDDLとは
一切関係がありません
とかだったら、
いいんですけどね! :)
ご清聴ありがとうございました
Upcoming SlideShare
Loading in...5
×

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

5,860

Published on

2013/10/25 MySQL Casual Talks #5

0 Comments
11 Likes
Statistics
Notes
  • Be the first to comment

No Downloads
Views
Total Views
5,860
On Slideshare
0
From Embeds
0
Number of Embeds
25
Actions
Shares
0
Downloads
9
Comments
0
Likes
11
Embeds 0
No embeds

No notes for slide

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

  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. ご清聴ありがとうございました
  1. A particular slide catching your eye?

    Clipping is a handy way to collect important slides you want to go back to later.

×