簡體   English   中英

如何從包含百萬條記錄的數據庫中選擇第一個“N”條記錄?

[英]How to select first 'N' records from a database containing million records?

我有一個填充了百萬條記錄的oracle數據庫。 我正在嘗試編寫一個SQL查詢,該查詢根據特定條件從數據庫返回第一個“N”個排序記錄(比如100條記錄)。

SELECT * 
FROM myTable 
Where SIZE > 2000 
ORDER BY NAME DESC

然后以編程方式選擇前N個記錄。

這種方法的問題是:

  • 查詢結果為50萬條記錄,“ORDER BY NAME”導致所有記錄按降序排序在NAME上。 這種分類花費了大量時間。 (將近30-40秒。如果我省略ORDER BY,則只需1秒鍾)。
  • 排序后,我只對前N(100)條記錄感興趣。 因此,完整記錄的排序無用。

我的問題是:

  1. 是否可以在查詢中指定“N”? (這樣排序僅適用於N條記錄,查詢變得更快)。
  2. 在SQL中有任何更好的方法來改進查詢以僅排序N個元素並在快速時間內返回。

如果您的目的是找到100個隨機行並在之后對它們進行排序,那么Lasse的解決方案是正確的。 如果我認為您希望按名稱排序前100行而丟棄其他行,則可以構建如下查詢:

SELECT * 
  FROM (SELECT * 
          FROM myTable 
         WHERE SIZE > 2000 ORDER BY NAME DESC) 
 WHERE ROWNUM <= 100

優化器將理解它是一個TOP-N查詢,並且能夠在NAME上使用索引。 它不必對整個結果集進行排序,它只會從索引的末尾開始並向后讀取並在100行后停止。

您還可以向原始查詢添加提示,以使優化器了解您只對第一行感興趣。 這可能會生成類似的訪問路徑:

SELECT /*+ FIRST_ROWS*/* FROM myTable WHERE SIZE > 2000 ORDER BY NAME DESC

編輯:只是在查詢中添加AND rownum <= 100將無效,因為Oracle rownum 排序之前被歸因:這就是你必須使用子查詢的原因。 如果沒有子查詢,Oracle將選擇100個隨機行,然后對它們進行排序。

顯示了如何根據您的Oracle版本選擇前N行。

從Oracle 9i開始,RANK()和DENSE_RANK()函數可用於確定TOP N行。 例子:

根據工資獲得前10名員工

SELECT ename,sal FROM(SELECT ename,sal,RANK()OVER(ORDER BY sal DESC)sal_rank FROM emp)WHERE sal_rank <= 10;

選擇排名前10位的員工

SELECT ename,sal FROM(SELECT ename,sal,DENSE_RANK()OVER(ORDER BY sal DESC)sal_dense_rank FROM emp)WHERE sal_dense_rank <= 10;

這里解釋兩者之間的區別

添加這個:

 AND rownum <= 100

你的WHERE子句。

但是,這不會做你所要求的。

如果要選擇100個隨機行,對它們進行排序,然后返回它們,則必須首先制定不帶ORDER BY的查詢,然后將其限制為100行,然后從中進行選擇並排序。

可能有效,但不幸的是我沒有可用於測試的Oracle服務器:

SELECT *
FROM (
    SELECT *
    FROM myTable
    WHERE SIZE > 2000
      AND rownum <= 100
    ) x
ORDER BY NAME DESC

但請注意那里的“隨機”部分,你說“給我100行SIZE> 2000,我不在乎哪100”。

這真的是你想要的嗎?

不,你實際上不會得到隨機結果,因為每次查詢服務器時它都會改變,但是你受到查詢優化器的支配。 如果該表的數據加載和索引統計信息隨時間發生變化,則在某些時候,您可能會獲得與上一個查詢不同的數據。

您的問題是每次運行查詢時都要進行排序。 您可以通過使用索引來消除排序操作 - 優化器可以使用索引來消除排序操作 - 如果排序列聲明為NOT NULL。

(如果列可以為空,則仍然可以通過(a)向查詢添加NOT NULL謂詞,或(b)添加基於函數的索引並相應地修改ORDER BY子句來實現。

僅供參考,在Oracle 12c中,可以使用FETCH子句完成此任務。 您可以在此處查看有關此事項的示例和其他參考鏈接。

暫無
暫無

聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.

 
粵ICP備18138465號  © 2020-2024 STACKOOM.COM