Location via proxy:   [ UP ]  
[Report a bug]   [Manage cookies]                
SlideShare a Scribd company logo
MySQLアンチパターン
という名の愚痴
2017/02/01
yoku0825
MySQL Casual Talks vol.10
\こんばんは/
yoku0825@とある企業のDBA
オラクれない-
ポスグれない-
マイエスキューエる-
カジュアる-
⽣息域
Twitter: @yoku0825-
Blog: ⽇々の覚書-
MyNA ML: ⽇本MySQLユーザ会-
MySQL Casualʼs Slack: MySQL Casual-
1/42
Congrats
MySQL Casual
Talks vol.10 !!
2/42
Thank you
Yahoo Japan
Corporation for
providing space!!
3/42
At first,
4/42
カシュッ
5/42
This is
痛み⽌め
6/42
Reference, SQLアンチパターン
7/42
Reference, SQLアンチパターン
個⼈的には実務経験積んでから、「やっぱアンチパターンな
のかよ︕」って⽅が捗ると思う
若いうちは「あっこれ 進研ゼミ SQLアンチパターンで⾒た
やつだ︕」ってなっても理解が得られずに⼼が死ぬことが多
い
今頃たぶんTwitterで「ウチはそんなことしないぞ」って技術的ホワ
イト企業の戦⼠たちが #mysqlcasual つけて呟いてる からみんな参
考にしよう
-
8/42
MySQLアンチパターン
なるべくSQLアンチパターンに載っているアンチパターン以
外で
これをやると MySQLはカジュア
ルに死ぬ ものを集めてみたつもり
9/42
おしながき
まさかのtempテーブル1.
アンリーダブルSQL2.
MySQLはJOINが遅い、非正規化すれば速くなる3.
サブクエリー忌避症候群4.
みんなだいすきER図5.
200 Internal Server Error6.
ザ・オブジェクト命名規則7.
DBMS・ザ・オラクルマシン8.
ぼくのかんがえたさいきょうの⽌まらないサービス9.
詫び⽯はロックを取らない10.
野良MySQL 5.7が360⽇でパスワードエクスパイア11.
10/42
1. まさかのtempテーブル
「⼀時的に作ったテーブル」じゃなくて、「⼀時変数を格納
するためのテーブル」だった時の衝撃
「RDBってアプリからすると⼀番アクセスしやすい永続化で
きるグローバル変数」
(c) jflute-
SQLアンチパターンのEAVに⾼確率でつながる
否定はできないしそういう使い⽅も悪いもんじゃないが、同
じセリフを正規化できない⼈に⾔われると途端に時限爆弾の
気配がする
11/42
1. まさかのtempテーブル
RDBはテキストファイルやmemcachedに突っ込んだものよ
りよほど容量を⾷う
ストレージもメモリーも⾷う
何のためにそんなにゴテゴテ使うかというと、トランザクシ
ョンによるデータの保護とSQLによる範囲検索のため
「キャッシュミスヒットするグローバル変数」の想像がつか
ないなら、メモリーは⼤きめに
12/42
2. アンリーダブルSQL
select super_long_column_name a, yet_another_long_column_name
b, .. from super_long_table_name t left join more_long_long_table
_name t0 on .. where .. group by t.a, t.b order by ..
13/42
2. アンリーダブルSQL
全部⼩⽂字(または全部⼤⽂字)
1⽂字エイリアス
特に “a” とか “t” とか目grepできないよ-
EXPLAINの結果って全部エイリアスで表⽰されちゃうんだ-
よってEXPLAINの結果が非常に読みにくい、追いにくい-
14/42
2. アンリーダブルSQL
SQLキーワードは⼤⽂字、オブジェクト名は⼩⽂字で
AS を(キーワードとして⼤⽂字で)使う
⼊ってればまだそこを目安にエイリアスが探せる-
1⽂字エイリアスは使わない。せめて1単語以上
毎回⼿で打つわけじゃないんだから、多少のタイプ数増加で助かる命
がある
-
15/42
2. アンリーダブルSQL
SELECT super_long_column_name AS long_column, yet_another_long_co
lumn_name ya_long_column, .. FROM super_long_table_name AS long_t
able LEFT JOIN more_long_long_table_name AS more_long ON .. WHER
E .. GROUP BY long_table.long_column, long_table.ya_long_column O
RDER BY ..
16/42
( ´-`).oO(改⾏
⼊れないと全然綺
麗になったように
⾒えない
17/42
3. MySQLはJOINが遅い、非正規化すれば速くなる
って⾔ってる⼈のクエリーはだいたい、非正規化してもまた
しばらくたつと遅くなる
計測した結果⼀度は速くなるから「この選択肢は間違ってな
かった」って経験になる
あとこの⽂脈で「正規形」「非正規化」って⾔われるのは本
来の正規形の話ではなく単なるテーブル分割であることがま
れにだがよくある
18/42
3. MySQLはJOINが遅い、非正規化すれば速くなる
⼤概遅いのはJOINそのものでなく、 ORDER BY狙いのキー
や GROUP BY狙いのキーが上⼿く使えてないこと(あるい
は、ちゃんと波及させられていないこと)
NLJの仕組みがわかれば非正規化しなくても⾼速化できるよ
See also WHERE狙いのキー、ORDER BY狙いのキー
19/42
4. サブクエリー忌避症候群
SELECT ..
FROM user_main
WHERE user_id IN (SELECT user_id FROM black_list) AND ..
↓
SELECT ..
FROM user_main JOIN black_list USING(user_id)
WHERE ..
20/42
4. サブクエリー忌避症候群
「MySQLのサブクエリーは遅いので、JOINに書き換えまし
た︕」
わかる。でもサブクエリーの⽅がリーダブルなSQLではあるよね。
「MySQLのサブクエリーは遅いので、テンポラリーテーブルに
⼊れてキャッシャブルにします︕」
すごい。歴戦のMySQLerっぽい。
「MySQLのサブクエリーは遅いので、アプリケーション側でル
ープしてフィルタしてます︕」
( д ) ゚ ゚ ファッ!?
21/42
4. サブクエリー忌避症候群
MySQLには 遅いサブクエリー と 遅くないサブクエリー が
ある
サブクエリーなら何でもかんでも回避するってもんでもない-
キャッシャブルな(遅くない)サブクエリーは視認性を上げることも
ある
-
特にこのあたりのオプティマイザーの挙動は5.6, 5.7と良く
なって来ているので、バージョンアップするだけで桁違いの
速度が出ることが
実際この前⾒たけどびっくりした-
22/42
5. みんなだいすきER図
メンテされてないER図があるじゃろ︖
引継ぎのために今、2週間かけて現在の状態に整備するじゃ
ろ︖
「テーブル定義が更新されるたびにER図も更新するこ
と︕」ってコメントをつけるじゃろ︖
でもER図はpngだったりパワーポイントだったりするじゃ
ろ︖
pngの更新なんて⾯倒じゃろ︖
次の引継ぎの時にまた同じことが起こるんじゃ
23/42
5. みんなだいすきER図
ER図は必ずDDLから機械的に⽣成できるようにする
ぎっちりFK張る、または、1ドメイン1命名を徹底する
1ドメイン1命名っていうのは、 users.id = tweets.user_id じゃなくて
users.user_id = tweets.user_id ってカラム名をそろえること
これなら機械的にERが⽣成できる(たとえばMySQL Workbench)
-
あるいはそういうリレーションシップ(Not リレーション)を管理で
きるフレームワークもあるとかないとか
-
24/42
6. 200 Internal Server Error
return $conn->selectrow_hashref($sql, undef, @param);
my $ret;
eval
{
$ret= $conn->selectrow_hashref("SELECT COUNT(*) AS c FROM ..")-
>{c};
};
$ret= 0 if $@;
return $ret;
25/42
6. 200 Internal Server Error
エラーで結果セットが空っぽなのと、条件に1⾏もマッチし
ないのがどっちもundefとか
異常系と数値の0が区別されてないとか
画⾯には「条件にマッチする⾏はありませんでした(に
こ)」って出てきて
外形テスト通っちゃうやつな︕
26/42
6. 200 Internal Server Error
嘘だと思うだろ︖ あるんだぜ、本当に。
油断はするな、くれぐれも。
27/42
7. ザ・オブジェクト命名規則
sub main
{
my ($argv1, $argv2, @option)= @_;
my $argv3;
if (&validate($argv1, $argv2))
{
$argv3= 1;
}
}
28/42
7. ザ・オブジェクト命名規則
$argv1 は許されないのに flg1 が許される世界線
特に悲惨なのはインデックス。 idx_tablename_01 なんて何
の情報量もない
インデックス名なんて意識する必要がない︖-
EXPLAIN⾒る時とロック解析する時は必須-
DBAにもDBAなりの「リーダブル・ネーム」がある
29/42
7. ザ・オブジェクト命名規則
オブジェクト名は⼩⽂字がいい(Recollect アンリーダブル
SQL)
「英2単語以上から成る “̲” 区切りの⽂字列」がオススメ
MySQL上で “̲”, “$”, 以外の記号はクォートが必要-
⼆単語以上アンダースコアで区切った予約語なんて
“STRAIGHT̲JOIN” くらいだから予約語の⼼配もない
-
インデックスの命名は idx_col1_col2_col3 (col1, col2,
col3) がオススメ
EXPLAINした時にどのカラムをカバーしてるのかわかりやすい-
30/42
8. RDBMS・ザ・オラクルマシン
本来の 神託機械 とはちょっと違う意味で
SQLという祝詞をDBMSという祭壇に捧げれてお祈りしてい
れば、そのうち神託のように(正しい)答えが返ってくるこ
とを期待する⽅々ガイル
Oracle使いにそういう⼈が多い-
そのSQL、どんなにお祈りしてもMySQLじゃ(現実的な時間では)返
ってこないよ
-
31/42
8. RDBMS・ザ・オラクルマシン
RDBMSはあなたが開発しているのと同じ、何かの⽤途のた
めに作られた アプリケーション
似たようなサービスを開発しても会社や⼈によって実装が違
うように、同じRDBMSというくくりでも 実装によって得意
な処理と不得意な処理がそれぞれある
箸でもお好み焼きを焼けなくはないけど、できればヘラが欲しいね-
でもヘラじゃ⾖腐は⾷べにくいよねたぶん-
それぞれの特性を理解して使い分けられるようになるのが本
当のベンダーロックフリーでは
32/42
9. ぼくのかんがえたさいきょうの⽌まらないサービス
たとえばマスター昇格には必ず全ての更新が⽌まる瞬間が必
要で
たとえばロックっていう⼆重に処理したりするのを防ぐためのものと
⼀緒で
-
それを⽌めないということは、データが失われる/不整合が起きる可能
性があるってことで
-
Too many connectionsが出たようなもんだと思って数分くらい我慢
してほしい
-
不整合はサイレントに起こるので、エラーが返るよりよっぽ
どあとが⾯倒くさい
33/42
9. ぼくのかんがえたさいきょうの⽌まらないサービス
その「瞬間」をどれだけ短くするのかはこっちの腕の⾒せ所
だったりするので頑張る
データが壊れるかも知れない、書き込めないかも知れない作
業をするなら、メンテナンスを⾏う、あるいはエラーが出続
ける期間を許容するくらいの⼼の余裕は持っておいた⽅が良
いというか持ってください
34/42
10. 詫び⽯はロックを取らない
つまりはSQLアンチパターン キーレスエントリ
簡単にデッドロックの温床になるから張りたくない気持ちは
わかる
というか、正規化してるだけの分割ならPKでの結合になるから範囲は
思ったよりはひどくならないはず
-
非PKでもREAD-COMMITTEDだと幾分マシになるはず-
35/42
10. 詫び⽯はロックを取らない
事実は事実だけど、それを突き付けられるとDBAの⼼が折れ
る
今頃たぶんTwitterで「ウチはそんなことしないぞ」って技術的ホワイ
ト企業の戦⼠たちが以下略
-
FKでも綺麗に設計すれば詫び⽯なしでもいけるよ
FK綺麗に張るにはリレーショナルモデルの勉強をしましょ
う
36/42
11. 野良MySQL 5.7が360⽇でパスワードエクスパイア
ドSな 規格に縛られた腰の重いDBAに縛られずにMySQLを
使いたい︕
ドSな ⼝うるさいDBAにスキーマの⼝出しをされたくない︕
そうだ︕ ⾃分でMySQLを構築しよう︕
最新版の5.7.9(当時)や︕ (ドヤァ
37/42
11. 野良MySQL 5.7が360⽇でパスワードエクスパイア
DBAが設定を規格化してるのは管理コストの⾯だけじゃな
く 聖闘⼠は 同じ地雷を⼆度踏まない ためだったりもします
DBAはPITRやオンラインスキーマチェンジを⽇本語プロト
コルで受け付けるためのAPIみたいなもんです
バリバリ使ってください。ただしCPUは1個です。-
38/42
ボツになったネタたち
statusという名の論理削除
徹底節約︕ INT型 vs MEDIUMINT型
Too many connectionsのあとに
スレーブ1台で負荷分散するお︕
何もなかったことにする⾺⿅RDBMS(非strictモード)
誰でもroot
誰も知らないワーニング
39/42
ボツになったネタたち
油断できないテスト環境
読まれないエラーログ
腐った秘伝のタレ
リレーション IS NOT リレーションシップ
永久保管のデータ
5.0時代からのビュー嫌い
なんでも1ステートメントがクール
40/42
Questions
and/or
Suggestions?
41/42
Thank
you!!
42/42

More Related Content

MySQLアンチパターン