15章 ランダムセレクション
2014/02/27(金) SQLアンチパターン読書会
@natsu_nanana
自己紹介
■名前:なつなな(@natsu_nanana)
■仕事:webアプリケーションの開発してます。
    最近はソシャゲ案件やってます。
■言語:PHP、JavaScript(jquery)あたりが少々。
    最近はshellscr...
本日のパターン
ランダムセレクション
私の中のイメージ
利用シーン
■サイトに出す広告を複数の中からランダムに表示

■くじ引きで出す景品を複数の中からランダムに選択

■バグ修正担当者を開発チームのメンバーからランダムに選択
アンチパターン
■データをランダムにソートする
SELECT * FROM Bugs ORDER BY date_reported;
↑これは通常のソート
SELECT * FROM Bugs ORDER BY RAND() LIMIT1;
↑...
アンチパターンの見つけ方
■「SQLは行をランダムに返そうとすると本当に遅くなる」
■「アプリケーションへのメモリ割当を増やしたいんだけど。
一旦全ての行をアプリケーション上にフェッチしないとランダ
ムに1行を選択できないんだ」
■「一部のエン...
アンチパターンを用いても
良い場合

データセットが小さい場合
※ただし、重み付けが必要な場合等はデータセットが小さくても、適用できません
解決策
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から最大値間での間の値をランダムに選
択する。ただし、欠番が存在するため、ラ
ンダムに選ばれた値と必ずキー値が一致し
ない場合がある
[例]
欠番となるキー...
解決策・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からカウントした数までの
間のランダム値を取得する。
データ取得時はその値をオフセット値とし
...
解決策・4
ベンダー依存の解決策
■SQL Server2005の場合はTABLESAMPLE句が使える
■Oracleの場合はSAMPLE句が使える
以上、説明おわり
Upcoming SlideShare
Loading in …5
×

SQLアンチパターン読書会 15章 ランダムセレクション 説明資料

1,931 views

Published on

2014/02/27SQLアンチパターン読書会 「15章 ランダムセレクション」の説明資料

Published in: Technology
0 Comments
1 Like
Statistics
Notes
  • Be the first to comment

No Downloads
Views
Total views
1,931
On SlideShare
0
From Embeds
0
Number of Embeds
761
Actions
Shares
0
Downloads
6
Comments
0
Likes
1
Embeds 0
No embeds

No notes for slide

SQLアンチパターン読書会 15章 ランダムセレクション 説明資料

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

×