論oracle隨機查詢一條記錄


      這幾天工作上的需要,要從一個比較大的表中隨機取出一條記錄,oracle 不像MS SQLSERVER那樣,直接用Select TOP 1 * From TABLE Order By NewID(),就能高效的隨機查出一條記錄。經過一翻折騰,用一個有90萬條記錄的表t_id,只有一個gameid字段,該字段上沒有索引,表里就是從100000到999999一連串的數據記錄,進行測試:

     方法1.

    采用rownum和dbms_random.value,平均用時5秒,這個效率確實是太低了,對於小表應該還行,大表那就太不適合了。

       declare
       n_id number(6);
       begin
               SELECT gameid into n_id FROM(SELECT gameid FROM t_id T ORDER BY dbms_random.value()) WHERE ROWNUM=1;
               dbms_output.put_line(to_char(n_id));
       end;
       /

    方法2. 

   采用oracle sample語法,設置隨機樣本是1%,結果用時0.01左右,速度是相當快的,但是根據官網的說法,采用sample采集特性可能會產生不准確的結果集,我在測試中是沒有碰到不正確的結果。但是有個問題,就是隨機的結果分布很不平均,結果幾乎都分內存卡在100000-200000的記錄中。效率雖好,但並沒有達到很好的隨機效果,如果對於結果的要求不是很高的,這個方法是相當不錯的。

       declare
            n_id number(6);
       begin
             SELECT gameid into n_id FROM t_id  SAMPLE (1)  WHERE ROWNUM = 1;
             dbms_output.put_line(to_char(n_id));
       end;
       /

      方法3. 

      采用minus語法,先隨機獲取一個在表總記錄數范圍內的一個隨機數,再通過rownum查詢兩個結果集只相差一條記錄,用minus相減留出事先隨機數的那條記錄,平均用時大概1秒,隨機數越小,查詢速度越快,當隨機數是20000時,用於0.016秒。該方法雖然

能得到很有隨機效果,但效率比較不上該方法2. 對效率要求一般的話, 還是可以考慮使用的。

declare
  n_count int:=0;
  n_rand_num int:=0;
  n_id number(6);
begin
  SELECT COUNT(*) INTO n_count FROM  t_id;
  SELECT  trunc(dbms_random.value(1,n_count+1)) INTO n_rand_num FROM DUAL;

  select gameid into n_id from (SELECT gameid FROM t_id T WHERE rownum<n_rand_num
  minus
  SELECT gameid FROM t_id T WHERE rownum<n_rand_num-1);
  dbms_output.put_line(to_char(n_id));
end;
/

 

還有別的方法,可以參考下http://www.oracle.com.cn/viewthread.php?tid=130433&extra=page%3D1

 
里面討論了一些方法,其中版主增加一個ROWNUM的字段並加索引,這種情況一個要改變表結構,另一個情況是有些記錄是要排除在隨機查詢以外的,就不好處理了。


免責聲明!

本站轉載的文章為個人學習借鑒使用,本站對版權不負任何法律責任。如果侵犯了您的隱私權益,請聯系本站郵箱yoyou2525@163.com刪除。



 
粵ICP備18138465號   © 2018-2025 CODEPRJ.COM