SQLアンチパターン読書会 15章 ランダムセレクション 説明資料
-
Upload
nao-yamamoto -
Category
Technology
-
view
891 -
download
7
Transcript of SQLアンチパターン読書会 15章 ランダムセレクション 説明資料
15章 ランダムセレクション
2014/02/27(金) SQLアンチパターン読書会@natsu_nanana
自己紹介
■名前:なつなな(@natsu_nanana)
■仕事:webアプリケーションの開発してます。 最近はソシャゲ案件やってます。
■言語:PHP、JavaScript(jquery)あたりが少々。 最近はshellscript(bash)が楽しいです。
本日のパターン
ランダムセレクション
私の中のイメージ
利用シーン
■くじ引きで出す景品を複数の中からランダムに選択
■バグ修正担当者を開発チームのメンバーからランダムに選択
■サイトに出す広告を複数の中からランダムに表示
アンチパターン
SELECT * FROM Bugs ORDER BY date_reported;
SELECT * FROM Bugs ORDER BY RAND() LIMIT1;
インデックスが効かない!!
(テーブルスキャンが行われる)
■データをランダムにソートする
↑これはランダムにソートをしている
↑これは通常のソート
※余談ですが、「MYSql ランダム」でググるとこのやり方のポストが結構出てきます
アンチパターンの見つけ方
■「アプリケーションへのメモリ割当を増やしたいんだけど。
一旦全ての行をアプリケーション上にフェッチしないとランダ
ムに1行を選択できないんだ」
■「一部のエントリは、他に比べて表示される頻度が高いよう
に見える。この乱数発生器は平等に乱数を生成しているのだろ
うか?」
■「SQLは行をランダムに返そうとすると本当に遅くなる」
「ランダムに選択」「乱数が」という言葉が出てくる場合はこのアンチパターンを
疑って良いかと思う
アンチパターンを用いても良い場合
データセットが小さい場合※ただし、重み付けが必要な場合等はデータセットが小さくても、適用できません
解決策
1.1と最大値の間のランダムなキー値を選択する
→欠番の穴の後にあるキー値を選択する
2.全てのキー値リストを受け取り、ランダムに一つを選択する
3.オフセットを用いてランダムに行を選択する
4.ベンダー依存の解決策
解決策・1欠番のないキー値の場合
1
2
3
4
5
6
7
8
9
10
11
1と最大値(この例だと11)の間の値をランダムに選択する。ランダムに選ばれた値と必ずキー値は必ず一致する
[問題点]
キー値が全て使用されていない(欠番)と
選ばれた値が行と一致しない可能性が発
生する
解決策・1欠番のあるキー値の場合
1
2
3
4
5
6
7
8
9
10
11
1から最大値間での間の値をランダムに選択する。ただし、欠番が存在するため、ランダムに選ばれた値と必ずキー値が一致しない場合がある[例]欠番となるキー値4が選択された場合次のキー値5が選択される
[問題点]
キー値5はランダムに選ばれた値が4or5の
場合に選ばれる為、他の値と比べて選択さ
れる頻度が上がる
解決策・2キーリストを利用
1
3
6
8
13
14
15
20
23
26
27
最初にキー値のリストを取得する。取得したリストの中からランダムにキー値を選択。その後、選択したキー値を元に対象データを取得
[問題点]
リストが大きいとメモリリソースを超えてエ
ラーとなる
解決策・3オフセット値を利用
1
3
6
8
13
14
15
20
23
26
27
COUNT関数を利用して対象データの行数をカウントし、0からカウントした数までの間のランダム値を取得する。データ取得時はその値をオフセット値として使用する。
※oracle、SQLServer、DB2ではrow_number
関数が使えます
SELECT * FROM Bugs LIMIT 1 OFFSET :offset;
SELECT ROUND(RAND() * (SELECT COUNT(*) FROM Bugs))
AS offset;
上で取得したoffset
解決策・4ベンダー依存の解決策
■SQL Server2005の場合はTABLESAMPLE句が使える
■Oracleの場合はSAMPLE句が使える
以上、説明おわり