SlideShare a Scribd company logo
1 of 34
Download to read offline
MySQLで論理削除と正しく付き合う
⽅法
2015/08/31
yoku0825
論理削除 Casual Talks #1
元のタイトルは
“MySQLの論理削
除はどうして速い
のか”
1/33
DELETEじゃなく
てUPDATEだか
ら、という出落ち
ネタ
2/33
論理削除についてど
う思うか、それぞれ
の⽴場の⼈(︖)に
聞いてみました
3/33
論理削除についてのそれぞれの⾒解
とある企業のDBA
よく考えたら反対する理由があんまりないことに気付いた
MySQL
UPDATEじゃんそれ
InnoDB
うん、よくやるよくやる
4/33
みたいな
5/33
とはいえ書い
てて何となく
思い当たる
6/33
MySQLの都合に沿
って 論理削除すれ
ば 必要悪 っぽいけ
ど
7/33
そうでない場
合は単なる 害
悪
8/33
Using where;
とか Using
filesort; の温床
9/33
という訳でなんか
その辺を整理して
みようと思います
10/33
\こんばんは/
yoku0825@とある企業のDBA
オラクれない-
ポスグれない-
マイエスキューエる-
家に帰ると
妻の夫-
せがれの⽗-
ムスメの⽗-
Twitter: @yoku0825
Blog: ⽇々の覚書
MyNA ML: ⽇本MySQLユーザ会
11/33
※個⼈の⾒解であり、所
属する組織あるいは所属
しない組織の意⾒を代表
するわけがありません
12/33
ちょっと待て︕ そ
のカラムNOT
NULL制約ついて
る︕︖
13/33
( ゚д゚) ハッ
14/33
※個⼈の⾒解であり、所
属する組織あるいは所属
しない組織あるいは
NULLの意⾒を代表する
わけがありません
15/33
個⼈の意⾒
本当はしてほしくない
余計なカラムは増えて欲しくないし-
参照されないデータは⼊っていて欲しくない-
テーブル設計的に汚い-
個⼈的に⼀番好きなのはDELETEトリガーでアーカイブ⽤の
テーブルに追い出しちゃうこと
カジュアルに元テーブルにADD COLUMNしてアーカイブ⽤のテーブ
ルにADD COLUMNを忘れるとトリガーが腐ってひどいことに
-
16/33
よく考えること
UNIQUE制約さん息してない
カラムぶんデータのサイズが⼤きくなる
削除されなかったレコードがゴミとしてたまる
covering index狙いにくい
WHERE狙いのキーはなんとかなるかも知れないけど-
ORDER BY狙いのキーでだいたい死ぬ-
17/33
んー︖
UNIQUE制約さん息してない
でも残念ながらナチュラルキーがしっかり定義してあるテーブルの⽅
が少ない
-
カラムぶんデータのサイズが⼤きくなる
TINYINTなら(1バイト * レコード数) * (1 + セカンダリーインデッ
クス数)
数千万レコード8インデックスくらいならせいぜい数百メガバイト
これが⼗ギガバイト単位になるなら考え直した⽅がいいかも
-
18/33
あれ︖
削除されなかったレコードがゴミとしてたまる
そもそもWEBサービス削除少ない-
みんなだいすきtpcc-mysqlだと1/47より少ない(内部でカーソル回し
てるのでSELECTもうちょっと多いはず)
-
deliveryの中だけで⾒て1/7
体感、もっと少ないと思う
-
100GBのレコードの1%が削除されるとして1GBなら誤差範囲なんじ
ゃ︖ (⼈によるかな)
-
covering index狙いにくい
狙いにくくはあるけどちゃんとインデックス設計してWHEREの先頭
で必ず指定するようにすれば狙っていける
-
19/33
前提
サロゲートキーが振られていて、他にユニーク制約がない
削除フラグのカラムはboolかせめてENUM
削除フラグのカラムは全てのセカンダリーインデックスの先
頭に振られている
MySQLが5.5以降でない (ごめんなさい当⽇「5.5以降であ
ること」みたいに話してましたが逆でした。。)
UPDATEで済ませないといけない理由がある
削除されたデータに運営やバッチがアクセスする-
ユーザートラフィックのくせに削除の対象レコードが数万規模-
20/33
サロゲートキー
ナチュラルキーがある場合に論理削除しちゃうとナチュラル
キーで制約できない
残念ながらナチュラルキーが使われてるケースの⽅が少ない
ナチュラルキー, サロゲートキーは宗教戦争になるので、ウチではサ
ロゲートキーが主流なので忌避する理由にならない、とだけ⾔ってお
きます
-
「 サロゲートキーの毒を⾷らわば論理削除の皿まで 」って感じ-
21/33
削除フラグの型
DATETIME型, TIMESTAMP型は変
NULLABLE⼤前提になる-
“削除されているかどうか”というドメインと”いつ削除されたか”とい
うドメインが1つのカラムで表現される
-
リレーショナルモデル的に間違ってる-
bool型なら”= 0”で等価検索できるのでインデックスが上⼿く使える-
22/33
削除 フラグ︖
というかそもそも論理 削除 とか 削除 フラグなんていうか
ら話が掴みにくくなる
スーパー非表⽰フラグとか表⽰ステータスとかにすればいいんじゃ
ね︖
-
そうすれば、それはレコードの 属性 の⼀つなので、リレーショナル
モデル的に納得がいく
運営のみ閲覧可能フラグとかユーザー非表⽰フラグとかでもいい
ステータスならENUM(ʻNOT̲DELETEDʼ, ʻDELETED̲BY̲USERʼ,
ʻDELETED̲BECAUSE̲DMCAʼ, ʻDELETED̲BECAUSE̲PORNʼ, ..)とか︖
ただし”display̲status <> ʻNOT̲DELETEDʼ“とかやると死ねる。
とはいえそんなクエリー流すの管理画⾯だけであるべきなので、テーブルスキャンく
らいは覚悟しろという気でいる。
-
23/33
削除フラグのインデックス
全てのセカンダリーインデックスの先頭に削除フラグのカラ
ムが存在しなければならない
本当は先頭じゃなくてもいいけど(カーディナリティー2だし)「先
頭じゃなくていい」って⾔って変なところに挟まれるくらいだったら
統⼀して先頭に「確実に」振ってほしい
-
24/33
削除フラグのインデックス
そして全ての(ユーザートラフィックによる)クエリーは
WHERE句の先頭で削除フラグのカラムを等価⽐較しなけれ
ばならない
たとえば”WHERE super̲hidden̲flag= 0 AND thread̲id= ?
ORDER BY comment̲date DESC” なら “KEY
(super̲hidden̲flag, thread̲id, comment̲date)”
-
AND演算⼦は等価交換できるから先頭じゃなくてもいいにしても、
super̲hidden̲flagが”=”演算⼦で評価されてないとこのインデック
スは使えない
だからboolがいい
-
というかユーザートラフィックから参照されるならそれ削除
じゃないよね
25/33
UPDATEとDELETEの違い
UPDATEでもDELETEでもインデックスを使ってレコードを
探す
DELETEの場合、クラスターインデックスのリーフを削除するので場
合によってはリバランスが⾛る
-
UPDATEの場合、クラスターインデックスのリーフが書き換わる
セカンダリーインデックスはチェンジバッファを使って非同期に更新される
DELETEの場合は最終的に全てのセカンダリーインデックスが更新される
UPDATEの場合はそのカラムが含まれるセカンダリーインデックスだけ更新される
super̲hidden̲flagが全部のセカンダリーインデックスの先頭にあると最終的なI/O
量の旨味は少ない
けどどうせ非同期だし意外と目をつむれる
-
26/33
MySQLが5.5 <del>以降</del> より前
チェンジバッファがDELETE, UPDATEに対応するのは
MySQL 5.5以降
チェンジバッファが効くとセカンダリーインデックス(プライマリ
ー, ユニークはダメ)への反映が非同期になる
-
“DELETE確かに遅いけど、そんなに⾔うほどでもなくね︖” と思った
らこれが効いているケースが多い
-
27/33
MySQLが5.5 <del>以降</del> より前
それ以前は インサートバッファ (INSERTにしかセカンダ
リーインデックスの非同期反映が有効でない)
DELETEはクラスターインデックスと全てのセカンダリーインデック
スを同期で反映させるのに対し
-
super̲hidden̲flagのUPDATEはクラスターインデックスはまず触ら
ないし、super̲hidden̲flagを含むセカンダリーインデックスだけ反
映させればいい
-
UPDATEにせよDELETEにせよ、MySQL 5.5とそれ以降にすることで
チェンジバッファの恩恵を受けられる
-
ということは別に前提ではないかも
28/33
じゃあ実際どれくらい違うかっていうと
次のページのグラフ
横軸はtpcc-mysqlのdeliveryトランザクションの経過時間
基本的に、最初がバッファプールあったまってなくてだんだんあった
まっていくので右に⾏くほどレイテンシーが下る
-
縦軸はレイテンシー、単位はミリ秒
⼩さければ⼩さいほどいい-
DELETE, UPDATEでただカラムを⾜しただけ, UPDATEでカ
ラムとインデックスを追加、の3パターン
トランザクション内のステートメントは7つ、対象をSELECTして
DELETEする2ステートメントが影響を受ける
-
29/33
微妙
super̲hidden̲flagを含めたインデックスを作らないとDELETE
より遅い(やっぱりSELECTが⾜を引っ張ってる)
30/33
UPDATEで済ませないといけない理由
“削除”されたデータにアクセス
“削除”された理由を解析しなければならない-
利⽤規約なのか法律なのかよく知らないけど、”いつ”削除されたのか
を保持しておく必要がある
-
非同期でS3のファイルを消したりするから、そっちの削除が終わるま
で取っておかないといけない
-
ユーザートラフィックなのに”削除”対象が数万レコード
Kazuho@Cybozu Labs: フレンド・タイムライン処理の原理と実践-
31/33
という訳で
サロゲートキーの毒を⾷らわば論理削除の皿まで
サロゲートキーじゃないといいことない-
インデックスがちゃんと切ってあればシステム的には⾔うほ
ど変わらない
DELETEされたレコードの⽐率が⼗分少ない場合に限る-
論理削除じゃなくて非表⽰状態へのUPDATEなんだっ⼿⽻先
32/33
Questions and/or Suggestions?
Q. インデックスの先頭にカーディナリティーの⼩さい
super̲hidden̲flagを置くのは悪⼿じゃね︖
A. ちゃんと正しい位置に置いてくれるならどこでもいいんだけど、「先頭」
って⾔っておかないとだいたいひどいことになる
Q. DELETEトリガーでアーカイブテーブルに追い出すののデメ
リットはなんかある︖
A. トリガーはトラブルシュート⾯倒。ADD COLUMNしたらトリガーが腐っ
て全部のDELETEが転けるとか。
33/33

More Related Content

What's hot

Goのサーバサイド実装におけるレイヤ設計とレイヤ内実装について考える
Goのサーバサイド実装におけるレイヤ設計とレイヤ内実装について考えるGoのサーバサイド実装におけるレイヤ設計とレイヤ内実装について考える
Goのサーバサイド実装におけるレイヤ設計とレイヤ内実装について考える
pospome
 

What's hot (20)

SQLアンチパターン - 開発者を待ち受ける25の落とし穴 (拡大版)
SQLアンチパターン - 開発者を待ち受ける25の落とし穴 (拡大版)SQLアンチパターン - 開発者を待ち受ける25の落とし穴 (拡大版)
SQLアンチパターン - 開発者を待ち受ける25の落とし穴 (拡大版)
 
例外設計における大罪
例外設計における大罪例外設計における大罪
例外設計における大罪
 
DDD x CQRS 更新系と参照系で異なるORMを併用して上手くいった話
DDD x CQRS   更新系と参照系で異なるORMを併用して上手くいった話DDD x CQRS   更新系と参照系で異なるORMを併用して上手くいった話
DDD x CQRS 更新系と参照系で異なるORMを併用して上手くいった話
 
データベース設計徹底指南
データベース設計徹底指南データベース設計徹底指南
データベース設計徹底指南
 
世界一わかりやすいClean Architecture
世界一わかりやすいClean Architecture世界一わかりやすいClean Architecture
世界一わかりやすいClean Architecture
 
イミュータブルデータモデル(世代編)
イミュータブルデータモデル(世代編)イミュータブルデータモデル(世代編)
イミュータブルデータモデル(世代編)
 
マルチテナントのアプリケーション実装〜実践編〜
マルチテナントのアプリケーション実装〜実践編〜マルチテナントのアプリケーション実装〜実践編〜
マルチテナントのアプリケーション実装〜実践編〜
 
ドメインオブジェクトの見つけ方・作り方・育て方
ドメインオブジェクトの見つけ方・作り方・育て方ドメインオブジェクトの見つけ方・作り方・育て方
ドメインオブジェクトの見つけ方・作り方・育て方
 
なかったらINSERTしたいし、あるならロック取りたいやん?
なかったらINSERTしたいし、あるならロック取りたいやん?なかったらINSERTしたいし、あるならロック取りたいやん?
なかったらINSERTしたいし、あるならロック取りたいやん?
 
外部キー制約に伴うロックの小話
外部キー制約に伴うロックの小話外部キー制約に伴うロックの小話
外部キー制約に伴うロックの小話
 
MySQLアンチパターン
MySQLアンチパターンMySQLアンチパターン
MySQLアンチパターン
 
やはりお前らのMVCは間違っている
やはりお前らのMVCは間違っているやはりお前らのMVCは間違っている
やはりお前らのMVCは間違っている
 
SQLアンチパターン - ジェイウォーク
SQLアンチパターン - ジェイウォークSQLアンチパターン - ジェイウォーク
SQLアンチパターン - ジェイウォーク
 
雑なMySQLパフォーマンスチューニング
雑なMySQLパフォーマンスチューニング雑なMySQLパフォーマンスチューニング
雑なMySQLパフォーマンスチューニング
 
やってはいけない空振りDelete
やってはいけない空振りDeleteやってはいけない空振りDelete
やってはいけない空振りDelete
 
Goのサーバサイド実装におけるレイヤ設計とレイヤ内実装について考える
Goのサーバサイド実装におけるレイヤ設計とレイヤ内実装について考えるGoのサーバサイド実装におけるレイヤ設計とレイヤ内実装について考える
Goのサーバサイド実装におけるレイヤ設計とレイヤ内実装について考える
 
SQLアンチパターン メンター用資料
SQLアンチパターン メンター用資料SQLアンチパターン メンター用資料
SQLアンチパターン メンター用資料
 
MySQL 5.7にやられないためにおぼえておいてほしいこと
MySQL 5.7にやられないためにおぼえておいてほしいことMySQL 5.7にやられないためにおぼえておいてほしいこと
MySQL 5.7にやられないためにおぼえておいてほしいこと
 
マイクロにしすぎた結果がこれだよ!
マイクロにしすぎた結果がこれだよ!マイクロにしすぎた結果がこれだよ!
マイクロにしすぎた結果がこれだよ!
 
SQL大量発行処理をいかにして高速化するか
SQL大量発行処理をいかにして高速化するかSQL大量発行処理をいかにして高速化するか
SQL大量発行処理をいかにして高速化するか
 

More from yoku0825

MySQLステータスモニタリング
MySQLステータスモニタリングMySQLステータスモニタリング
MySQLステータスモニタリング
yoku0825
 

More from yoku0825 (20)

逝くぞ最新版、罠の貯蔵は十分か
逝くぞ最新版、罠の貯蔵は十分か逝くぞ最新版、罠の貯蔵は十分か
逝くぞ最新版、罠の貯蔵は十分か
 
サーバーが完膚なきまでに死んでもMySQLのデータを失わないための表技
サーバーが完膚なきまでに死んでもMySQLのデータを失わないための表技サーバーが完膚なきまでに死んでもMySQLのデータを失わないための表技
サーバーが完膚なきまでに死んでもMySQLのデータを失わないための表技
 
MySQLレプリケーションあれやこれや
MySQLレプリケーションあれやこれやMySQLレプリケーションあれやこれや
MySQLレプリケーションあれやこれや
 
MySQL 8.0で憶えておいてほしいこと
MySQL 8.0で憶えておいてほしいことMySQL 8.0で憶えておいてほしいこと
MySQL 8.0で憶えておいてほしいこと
 
片手間MySQLチューニング戦略
片手間MySQLチューニング戦略片手間MySQLチューニング戦略
片手間MySQLチューニング戦略
 
MySQLを割と一人で300台管理する技術
MySQLを割と一人で300台管理する技術MySQLを割と一人で300台管理する技術
MySQLを割と一人で300台管理する技術
 
MySQLステータスモニタリング
MySQLステータスモニタリングMySQLステータスモニタリング
MySQLステータスモニタリング
 
わかった気になるMySQL
わかった気になるMySQLわかった気になるMySQL
わかった気になるMySQL
 
わたしを支える技術
わたしを支える技術わたしを支える技術
わたしを支える技術
 
MySQL 5.7の次のMySQL 8.0はどんなものになるだろう
MySQL 5.7の次のMySQL 8.0はどんなものになるだろうMySQL 5.7の次のMySQL 8.0はどんなものになるだろう
MySQL 5.7の次のMySQL 8.0はどんなものになるだろう
 
Dockerイメージで誰でも気軽にMroonga体験
Dockerイメージで誰でも気軽にMroonga体験Dockerイメージで誰でも気軽にMroonga体験
Dockerイメージで誰でも気軽にMroonga体験
 
MySQLerの7つ道具 plus
MySQLerの7つ道具 plusMySQLerの7つ道具 plus
MySQLerの7つ道具 plus
 
MySQL 5.7の次のMySQLは
MySQL 5.7の次のMySQLはMySQL 5.7の次のMySQLは
MySQL 5.7の次のMySQLは
 
MySQLerの7つ道具
MySQLerの7つ道具MySQLerの7つ道具
MySQLerの7つ道具
 
MHAの次を目指す mikasafabric for MySQL
MHAの次を目指す mikasafabric for MySQLMHAの次を目指す mikasafabric for MySQL
MHAの次を目指す mikasafabric for MySQL
 
5.7の次のMySQL
5.7の次のMySQL5.7の次のMySQL
5.7の次のMySQL
 
mikasafabric for MySQL
mikasafabric for MySQLmikasafabric for MySQL
mikasafabric for MySQL
 
とあるイルカの近況報告
とあるイルカの近況報告とあるイルカの近況報告
とあるイルカの近況報告
 
MySQL Fabricでぼっこぼこにされたはなし
MySQL FabricでぼっこぼこにされたはなしMySQL Fabricでぼっこぼこにされたはなし
MySQL Fabricでぼっこぼこにされたはなし
 
MySQLと正規形のはなし
MySQLと正規形のはなしMySQLと正規形のはなし
MySQLと正規形のはなし
 

Recently uploaded

Recently uploaded (11)

Observabilityは従来型の監視と何が違うのか(キンドリルジャパン社内勉強会:2022年10月27日発表)
Observabilityは従来型の監視と何が違うのか(キンドリルジャパン社内勉強会:2022年10月27日発表)Observabilityは従来型の監視と何が違うのか(キンドリルジャパン社内勉強会:2022年10月27日発表)
Observabilityは従来型の監視と何が違うのか(キンドリルジャパン社内勉強会:2022年10月27日発表)
 
LoRaWANスマート距離検出センサー DS20L カタログ LiDARデバイス
LoRaWANスマート距離検出センサー  DS20L  カタログ  LiDARデバイスLoRaWANスマート距離検出センサー  DS20L  カタログ  LiDARデバイス
LoRaWANスマート距離検出センサー DS20L カタログ LiDARデバイス
 
新人研修 後半 2024/04/26の勉強会で発表されたものです。
新人研修 後半        2024/04/26の勉強会で発表されたものです。新人研修 後半        2024/04/26の勉強会で発表されたものです。
新人研修 後半 2024/04/26の勉強会で発表されたものです。
 
論文紹介:Video-GroundingDINO: Towards Open-Vocabulary Spatio-Temporal Video Groun...
論文紹介:Video-GroundingDINO: Towards Open-Vocabulary Spatio-Temporal Video Groun...論文紹介:Video-GroundingDINO: Towards Open-Vocabulary Spatio-Temporal Video Groun...
論文紹介:Video-GroundingDINO: Towards Open-Vocabulary Spatio-Temporal Video Groun...
 
Amazon SES を勉強してみる その22024/04/26の勉強会で発表されたものです。
Amazon SES を勉強してみる その22024/04/26の勉強会で発表されたものです。Amazon SES を勉強してみる その22024/04/26の勉強会で発表されたものです。
Amazon SES を勉強してみる その22024/04/26の勉強会で発表されたものです。
 
論文紹介: The Surprising Effectiveness of PPO in Cooperative Multi-Agent Games
論文紹介: The Surprising Effectiveness of PPO in Cooperative Multi-Agent Games論文紹介: The Surprising Effectiveness of PPO in Cooperative Multi-Agent Games
論文紹介: The Surprising Effectiveness of PPO in Cooperative Multi-Agent Games
 
Amazon SES を勉強してみる その32024/04/26の勉強会で発表されたものです。
Amazon SES を勉強してみる その32024/04/26の勉強会で発表されたものです。Amazon SES を勉強してみる その32024/04/26の勉強会で発表されたものです。
Amazon SES を勉強してみる その32024/04/26の勉強会で発表されたものです。
 
知識ゼロの営業マンでもできた!超速で初心者を脱する、悪魔的学習ステップ3選.pptx
知識ゼロの営業マンでもできた!超速で初心者を脱する、悪魔的学習ステップ3選.pptx知識ゼロの営業マンでもできた!超速で初心者を脱する、悪魔的学習ステップ3選.pptx
知識ゼロの営業マンでもできた!超速で初心者を脱する、悪魔的学習ステップ3選.pptx
 
Utilizing Ballerina for Cloud Native Integrations
Utilizing Ballerina for Cloud Native IntegrationsUtilizing Ballerina for Cloud Native Integrations
Utilizing Ballerina for Cloud Native Integrations
 
論文紹介:Selective Structured State-Spaces for Long-Form Video Understanding
論文紹介:Selective Structured State-Spaces for Long-Form Video Understanding論文紹介:Selective Structured State-Spaces for Long-Form Video Understanding
論文紹介:Selective Structured State-Spaces for Long-Form Video Understanding
 
LoRaWAN スマート距離検出デバイスDS20L日本語マニュアル
LoRaWAN スマート距離検出デバイスDS20L日本語マニュアルLoRaWAN スマート距離検出デバイスDS20L日本語マニュアル
LoRaWAN スマート距離検出デバイスDS20L日本語マニュアル
 

MySQLで論理削除と正しく付き合う方法