とあるイルカのバーボンハウス
DESCRIPTION
2013/10/25 MySQL Casual Talks #5TRANSCRIPT
とあるイルカのバーボンハウス
2013/10/25yoku0825
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, `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;
うん、「また」なんだ。済まない。仏の顔もって言うしね、
謝って許してもらおうとも思っていない。
でも、この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, `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;
`オンラインでは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, `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;
なぜサロゲートキーを
SIGNED BIGINTにした
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;
なぜ敢えて予約語を選んだ
KEY (`key`)とかギャグか
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;
容量がタイトなのに
何故バイナリー文字列をCHAR型にする
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;
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, `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;
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, `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;
何故その名前にしたのか
俺の目を見て言ってみろ
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;
情報量が全くない名前をつけるな
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;
aa_idはクラスタードインデックスだから
末尾につける必要はない
`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;
`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(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= utf8mb4PARTITION BY LIST(..) ..;
容量節約第一
ただし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 >= DATE_SUB(CURRENT_DATE, INTERVAL 30 DAY) -> ORDER BY aa_id desc\G*************************** 1. row *************************** id: 1 select_type: SIMPLE table: fugafuga type: rangepossible_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 filesort1 row in set (0.00 sec)
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 >= DATE_SUB(CURRENT_DATE, INTERVAL 30 DAY) -> ORDER BY aa_id desc\G*************************** 1. row *************************** id: 1 select_type: SIMPLE table: fugafuga type: rangepossible_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 filesort1 row in set (0.00 sec)
名前から型が推測できると更にすてき
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_status = xx -> AND cc_id > xx -> AND dd_date >= DATE_SUB(CURRENT_DATE, INTERVAL 30 DAY) -> ORDER BY aa_id desc\G*************************** 1. row *************************** id: 1 select_type: SIMPLE table: fugafuga type: rangepossible_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 filesort1 row in set (0.00 sec)
どこ狙ったのかがSQLだけで伝わる
アプリのコードに直接触ら(れ)ない
わたしにとってこれ意思疎通が超捗る
コードだけで会話する必要はないけど、
コードで判りあうことも必要
とはいえ、update_dateとか
フレームワークが自動で生成してるの
知りませんでしたorz
会話できるようになりたいorz
なお、このスライドは
フィクションであり、
実在するDDLとは
一切関係がありません
とかだったら、
いいんですけどね! :)
ご清聴ありがとうございました