查詢反模式 隨機選擇

2021-09-06 12:23:50 字數 2511 閱讀 4399

隨機數在資料庫中是經常用到的系統。 

在sql server中查詢隨機數最簡單的方法為:

select

top1

*from person order

bynewid()

以上sql語句的執行計畫如下:

以上這種方法,需要對整個表進行一次排序,而且還無法有效地使用索引。加入我們只需要前幾條資料,那麼好不容易對整個結果集完成了排序,但絕大多數都浪費了。

以上的方式缺點如下:

隨機排序的效能問題在資料量很小的時候是可容忍的。

假如我們要從中國23個省中隨機選擇乙個,那麼這是很快的,並且基本不會有改變。

1、從1到最大值之間的隨機選擇

這是一種避免對所有資料進行排序的方法,就是在1到最大的主鍵值之間隨機選擇1個。

不過,這個方案有乙個非常大的缺點,就是該方案假設主鍵的值是從1開始並保持連續的,這意味著在1到最大值之間沒有任何值是未使用的。如果當中漏掉一些值,那隨機獲得的主鍵可能取不到任何資料。當確信主鍵是從1到最大值連續的時候,可以使用這個方案。

select p1.*

from person as

p1   

inner

join (select

floor(rand() * (select

max(id) from person)) as rand_id) as

p2  

on p1.id = p2.rand_id

執行計畫如下:

由上面的執行計畫已經看出,已經不用排序了。

2、選擇下乙個最大值

這個方案和前乙個方案類似,但解決了在1到最大值之間主鍵有縫隙的情況,這個查詢會返回它隨機找到的第乙個有效值。

select

top1 p1.*

from person as

p1    

inner

join (select

floor(rand() * (select

max(id) from person)) as rand_id) as

p2  

on p1.id =

p2.rand_id

where p1.id >=

p2.rand_id

order

by p1.id

這個方法解決了隨機數沒有主鍵的情況,同時也意味著在乙個縫隙之後的那個值被選中的概率會增大。

當佇列中的縫隙不大並且每個值要被等概率選擇的重要性不高時,可以考慮這種方案。

3、高階程式獲取所有的鍵值,隨機選擇乙個

使用主程式**獲取所有的主鍵值,然後隨機選擇乙個。再使用這個隨機選擇出來的主鍵查詢完整的記錄。可以用如下的.net**實現:

random ran = new

random(10

);  ran.next();

使用高階程式獲取隨機數有如下缺點:

讀取整個表的主鍵出來,占用空間過多,可能超過記憶體上限。

查詢必須執行兩次:一次獲取主鍵的列表,第二次獲取對應的記錄。如果查詢太複雜或者太耗時,就會成為問題。

4、使用偏移量選擇隨機行

這種方案能夠避免之前幾個方案中的問題,那就是計算總的資料行數,隨機選擇0到總行數之間的乙個值,然後用這個值作為位移來獲取隨機行。

declare

@iint

--產生0到count()隨機數

select@i=

cast(ceiling(rand() *

count(*)) as

int) from

person1

--獲取行號等於隨機數的記錄

select

*from

(   

select personid,personname,row_number() over (order

by personid) as

rn   

from person1) as

t1   

where rn =

@i

當需要每行出現的概率相等,並且主鍵列是不連續的,可以使用這個方案。

5、專有解決方案

每種資料庫都可能針對這個需求提供獨有的解決方案,比如sql server 2005就增加了tablesample()函式。但是這個方法不能夠返回指定行數的記錄,可能會多點,也可能會少點。具體請了解函式說明:

select

*from person tablesample(50 rows);

SQL反模式筆記15 隨機排序

目標 隨即排序 反模式 使用rand 缺點是無法利用索引,而且是全表遍歷,效能太差 合理使用反模式 資料量很小的時候可以用 解決方案 1 使用隨機數 ceil rand select max id from t as randid 問題是,取出的id有可能是不存在的,因為id不是連續的 2 選擇下乙...

SQL反模式筆記18 使用 查詢

目標 減少輸入 反模式 使用 缺點1 傳輸的資料量大。解決方案 明確列出列名 這一章內容太簡單了,好像沒啥可說的。我想起用ibatis的時候遇到的乙個問題 最初的sql都是自動生成的,比如根據id update某個表,輸入引數是這個表對應的乙個entity,包含了這個表幾乎所有的字段。這樣使用的時候...

SQL反模式筆記16 模糊查詢

目標 模糊查詢 反模式 like 缺點 效能太差,無法使用索引,必須全表遍歷。合理使用反模式 資料量小 條件簡單時可以用。解決方案 使用特殊的搜尋引擎而不是sql 1 資料庫擴充套件,各大資料庫都有對全文檢索的解決方案,但是配置複雜。2 使用第三方搜尋引擎,比如lucene.3 實現自己的搜尋引擎 ...