精品伊人久久大香线蕉,开心久久婷婷综合中文字幕,杏田冲梨,人妻无码aⅴ不卡中文字幕

打開APP
userphoto
未登錄

開通VIP,暢享免費電子書等14項超值服

開通VIP
Oracle ROWNUM用法和分頁查詢總結(jié)
**********************************************************************************************************
[轉(zhuǎn)載]
Oracle的分頁查詢語句基本上可以按照本文給出的格式來進行套用。
Oracle分頁查詢格式(一):http://yangtingkun.itpub.net/post/468/100278
Oracle分頁查詢格式(二):http://yangtingkun.itpub.net/post/468/101703
Oracle分頁查詢格式(三):http://yangtingkun.itpub.net/post/468/104595
Oracle分頁查詢格式(四):http://yangtingkun.itpub.net/post/468/104867
Oracle分頁查詢格式(五):http://yangtingkun.itpub.net/post/468/107934
Oracle分頁查詢格式(六):http://yangtingkun.itpub.net/post/468/108677
Oracle分頁查詢格式(七):http://yangtingkun.itpub.net/post/468/109834
Oracle分頁查詢格式(八):http://yangtingkun.itpub.net/post/468/224557
Oracle分頁查詢格式(九):http://yangtingkun.itpub.net/post/468/224409
Oracle分頁查詢格式(十):http://yangtingkun.itpub.net/post/468/224823
Oracle分頁查詢的排序問題:http://yangtingkun.itpub.net/post/468/112274
Oracle官網(wǎng)連接查詢優(yōu)化的說明:http://docs.oracle.com/cd/E11882_01/server.112/e16638/optimops.htm#i36235
NESTED LOOP/HASH JOIN/SORT MERGE JOIN的區(qū)別:http://jewfinkl.blog.163.com/blog/static/14076982012431052316/
**********************************************************************************************************
根據(jù)以上文章進行了如下的總結(jié)。
ROWNUM
可能都知道ROWNUM只適用于小于或小于等于,如果進行等于判斷,那么只能等于1,不能進行大于的比較。
ROWNUM是oracle系統(tǒng)順序分配為從查詢返回的行的編號,返回的第一行分配的是1,第二行是2,依此類推。
ROWNUM總是從1開始,不管當前的記錄是否滿足查詢結(jié)果,ROWNUM返回的值都是1,如果這條記錄的值最終滿足所有的條件,那么ROWNUM會遞加,下一條記錄的ROWNUM會返回2,否則下一條記錄的ROWNUM仍然返回1。
理解了這一點,就清楚為什么一般的ROWNUM大于某個值或等于某個不為1的值是無法返回結(jié)果的,因此對于每條記錄的ROWNUM都是1,而ROWNUM為1不滿足查詢的結(jié)果,所以下一條記錄的ROWNUM不會遞增,仍然是1,因此所有的記錄都不滿足條件。
分頁查詢格式1
在查詢的最外層控制分頁的最小值和最大值。查詢語句如下:
[sql]
SELECT * FROM
(
SELECT A.*, ROWNUM RN
FROM (SELECT * FROM TABLE_NAME) A
)
WHERE RN BETWEEN 21 AND 40
分頁查詢格式2
[sql]
SELECT * FROM
(
SELECT A.*, ROWNUM RN
FROM (SELECT * FROM TABLE_NAME) A
WHERE ROWNUM <= 40
)
WHERE RN >= 21
分頁查詢格式3
考慮到多表聯(lián)合的情況,如果不介意在系統(tǒng)中使用HINT的話,可以將分頁的查詢語句改寫為:
[sql]
SELECT /*+ FIRST_ROWS */ * FROM
(
SELECT A.*, ROWNUM RN
FROM (SELECT * FROM TABLE_NAME) A
WHERE ROWNUM <= 40
)
WHERE RN >= 21
效率問題
對比這兩種寫法,絕大多數(shù)的情況下,第2個查詢的效率比第1個高得多。
這是由于CBO優(yōu)化模式下,Oracle可以將外層的查詢條件推到內(nèi)層查詢中,以提高內(nèi)層查詢的執(zhí)行效率。對于第2個查詢語句,第二層的查詢條件WHERE ROWNUM <= 40就可以被Oracle推入到內(nèi)層查詢中,這樣Oracle查詢的結(jié)果一旦超過了ROWNUM限制條件,就終止查詢將結(jié)果返回了。
而第1個查詢語句,由于查詢條件BETWEEN 21 AND 40是存在于查詢的第三層,而Oracle無法將第三層的查詢條件推到最內(nèi)層(即使推到最內(nèi)層也沒有意義,因為最內(nèi)層查詢不知道RN代表什么)。因此,對于第1個查詢語句,Oracle最內(nèi)層返回給中間層的是所有滿足條件的數(shù)據(jù),而中間層返回給最外層的也是所有數(shù)據(jù)。數(shù)據(jù)的過濾在最外層完成,顯然這個效率要比第一個查詢低得多。
上面分析的查詢不僅僅是針對單表的簡單查詢,對于最內(nèi)層查詢是復雜的多表聯(lián)合查詢或最內(nèi)層查詢包含排序的情況一樣有效。
觀察上面格式1和格式2二者的執(zhí)行計劃可以發(fā)現(xiàn),兩個執(zhí)行計劃唯一的區(qū)別就是格式2的查詢在COUNT這步使用了STOPKEY,也就是說,Oracle將ROWNUM <= 20推入到查詢內(nèi)層,當符合查詢的條件的記錄達到STOPKEY的值,則Oracle結(jié)束查詢。因此,可以預見,采用第二種方式,在翻頁的開始部分查詢速度很快,越到后面,效率越低,當翻到最后一頁,效率應(yīng)該和第一種方式接近。
分頁查詢語句之所以可以很快的返回結(jié)果,是因為它的目標是最快的返回第一條結(jié)果。如果每頁有20條記錄,目前翻到第5頁,那么只需要返回前100條記錄都可以滿足查詢的要求了,也許還有幾萬條記錄也符合查詢的條件,但是由于分頁的限制,在當前的查詢中可以忽略這些數(shù)據(jù),而只需盡快的返回前100條數(shù)據(jù)。這也是為什么在標準分頁查詢語句中經(jīng)常會使用FIRST_ROWS提示的原因。
對于行操作,可以在得到結(jié)果的同時將結(jié)果直接返回給上一層調(diào)用。但是對于結(jié)果集操作,Oracle必須得到結(jié)果集中所有的數(shù)據(jù),因此分頁查詢中所帶的ROWNUM信息不起左右。如果最內(nèi)層的子查詢中包含了下面這些操作中的一個以上,則分頁查詢語句無法體現(xiàn)出任何的性能優(yōu)勢:UNION、UNION ALL、MINUS、INTERSECT、GROUP BY、DISTINCT、UNIQUE以及聚集函數(shù)如MAX、MIN和分析函數(shù)等。
Oracle10g的新功能GROUP BY STOPKEY,使得Oracle10g解決了GROUP BY操作分頁效率低的問題。在10g以前,Oracle的GROUP BY操作必須完全執(zhí)行完,才能將結(jié)果返回給用戶。但是Oracle10g增加了GROUP BY STOPKEY執(zhí)行路徑,使得用戶在執(zhí)行GROUP BY操作時,可以根據(jù)STOPKEY隨時中止正在運行的操作。這使得標準分頁函數(shù)對于GROUP BY操作重新發(fā)揮了作用。
除了這些操作以外,分頁查詢還有一個很明顯的特點,就是處理的頁數(shù)越小,效率就越高,越到后面,查詢速度越慢。
分頁查詢用來提高返回速度的方法都是針對數(shù)據(jù)量較小的前N條記錄而言。無論是索引掃描,NESTED LOOP連接,還是ORDER BY STOPKEY,這些方法帶來性能提升的前提都是數(shù)據(jù)量比較小,一旦分頁到了最后幾頁,會發(fā)現(xiàn)這些方法不但沒有辦法帶來性能的提升,而且性能比普通查詢還要低得多。這一點,在使用分頁查詢的時候,一定要心里有數(shù)。
分頁查詢一般情況下,很少會翻到最后一篇,如果只是偶爾碰到這種情況,對系統(tǒng)性能不會有很大的影響,但是如果經(jīng)常碰到這種情況,在設(shè)計分頁查詢時應(yīng)該給予足夠的考慮。
多表聯(lián)合
下面簡單討論一下多表聯(lián)合的情況。對于最常見的等值表連接查詢,CBO一般可能會采用兩種連接方式NESTED LOOP和HASH JOIN(MERGE JOIN效率比HASH JOIN效率低,一般CBO不會考慮)。
一般對于大表查詢情況下,HASH JOIN的效率要比NESTED LOOP高很多,所以CBO一般默認會選擇HASH JOIN.
但是如果分頁查詢的內(nèi)層是這種連接查詢的話,使用NESTED LOOP可以更快的得到前N條記錄。
在這里,由于使用了分頁,因此指定了一個返回的最大記錄數(shù),NESTED LOOP在返回記錄數(shù)超過最大值時可以馬上停止并將結(jié)果返回給中間層,而HASH JOIN必須處理完所有結(jié)果集(MERGE JOIN也是)。那么在大部分的情況下,對于分頁查詢選擇NESTED LOOP作為查詢的連接方法具有較高的效率(分頁查詢的時候絕大部分的情況是查詢前幾頁的數(shù)據(jù),越靠后面的頁數(shù)訪問幾率越小)。
HASH JOIN中第一步也就是第一張表的全表掃描是無法應(yīng)用STOPKEY的,這就是NESTED LOOP比HASH JOIN優(yōu)勢的地方。
但是,如果恰好第一張表很小,對這張表的全掃描的代價極低,會顯得HASH JOIN效率更高。
如果兩張表的大小相近,或者Oracle錯誤的選擇了先掃描大表,則使用HASH JOIN的效率就會低得多。
因此對于表連接來說,在寫分頁查詢的時候,可以考慮增加FIRST_ROWS提示,它會導致CBO選擇NESTED LOOP,有助于更快的將查詢結(jié)果返回。
其實,不光是表連接,對于所有的分頁查詢都可以加上FIRST_ROWS提示。
不過需要注意的時,分頁查詢的目標是盡快的返回前N條記錄,因此,無論是ROWNUM還是FIRST_ROWS機制都是提高前幾頁的查詢速度,
對于分頁查詢的最后幾頁,采用HASH JOIN的方式,執(zhí)行效率幾乎沒有任何改變,而采用NESTED LOOP方式,則效率嚴重下降,而且遠遠低于HASH JOIN的方式。
排序列不唯一所帶來的問題
如果用來排序的列不唯一,也就是存在值相等的行,可能會造成第一次在前10條返回記錄中,某行數(shù)據(jù)出現(xiàn)了,而第二次在11到第20條記錄中,某行數(shù)據(jù)又出現(xiàn)了。一條數(shù)據(jù)重復出現(xiàn)兩次,就必然意味著有數(shù)據(jù)在兩次查詢中都不會出現(xiàn)。
其實造成這個問題的原因很簡單,是由于排序列不唯一造成的。Oracle這里使用的排序算法不具有穩(wěn)定性,也就是說,對于鍵值相等的數(shù)據(jù),這種算法完成排序后,不保證這些鍵值相等的數(shù)據(jù)保持排序前的順序。
解決這個問題其實也很簡單。有兩種方法可以考慮。
1)在使用不唯一的字段排序時,后面跟一個唯一的字段。
一般在排序字段后面跟一個主鍵就可以了,如果表不存在主鍵,跟ROWID也可以。這種方法最簡單,且對性能的影響最小。
2)另一種方法就是使用前面給出過多次的BETWEEN AND的方法。
這種方式由于采用表數(shù)據(jù)的全排序,每次只取全排序中的某一部分數(shù)據(jù),因此不會出現(xiàn)上面提到的重復數(shù)據(jù)問題。
但是正是由于使用了全排序,而且ROWNUM信息無法推到查詢內(nèi)部,導致這種寫法的執(zhí)行效率很低
測試結(jié)果
下面做一些測試,按照如下步驟準備數(shù)據(jù):
[sql]
CREATE TABLE T AS SELECT * FROM DBA_USERS;
CREATE TABLE T1 AS SELECT * FROM DBA_SOURCE;
ALTER TABLE T ADD CONSTRAINT PK_T PRIMARY KEY (USERNAME);
ALTER TABLE T1 ADD CONSTRAINT FK_T1_OWNER FOREIGN KEY (OWNER) REFERENCES T(USERNAME);
CREATE INDEX IND_T1_OWNER ON T1(OWNER);
EXEC DBMS_STATS.GATHER_TABLE_STATS(USER, 'T')
EXEC DBMS_STATS.GATHER_TABLE_STATS(USER, 'T1')
set autotrace traceonly
set timing on
現(xiàn)在表格T中有37行數(shù)據(jù),表格T1中有623K行數(shù)據(jù)。
比較格式1和格式2的查詢計劃
[sql]
--查詢語句1
SELECT * FROM
(
SELECT A.*, ROWNUM RN
FROM (SELECT * FROM T1) A
)
WHERE RN BETWEEN 21 AND 40;
--查詢語句2
SELECT * FROM
(
SELECT A.*, ROWNUM RN
FROM (SELECT * FROM T1) A
WHERE ROWNUM <= 40
)
WHERE RN >= 21;
執(zhí)行計劃執(zhí)行時間統(tǒng)計信息
查詢語句1
----------------------------------------------------------
Plan hash value: 3921461035
----------------------------------------------------------------------------
| Id  | Operation           | Name | Rows  | Bytes | Cost (%CPU)| Time     |
----------------------------------------------------------------------------
|   0 | SELECT STATEMENT    |      |   623K|  1231M|  2879   (1)| 00:00:35 |
|*  1 |  VIEW               |      |   623K|  1231M|  2879   (1)| 00:00:35 |
|   2 |   COUNT             |      |       |       |            |          |
|   3 |    TABLE ACCESS FULL| T1   |   623K|    59M|  2879   (1)| 00:00:35 |
----------------------------------------------------------------------------
Predicate Information (identified by operation id):
---------------------------------------------------
1 - filter("RN"<=40 AND "RN">=21)
00: 00: 02.401  recursive calls
0  db block gets
10441  consistent gets
10435  physical reads
0  redo size
1720  bytes sent via SQL*Net to client
431  bytes received via SQL*Net from client
3  SQL*Net roundtrips to/from client
0  sorts (memory)
0  sorts (disk)
20  rows processed
查詢語句2
----------------------------------------------------------------------------
| Id  | Operation           | Name | Rows  | Bytes | Cost (%CPU)| Time     |
----------------------------------------------------------------------------
|   0 | SELECT STATEMENT    |      |    40 | 82800 |     2   (0)| 00:00:01 |
|*  1 |  VIEW               |      |    40 | 82800 |     2   (0)| 00:00:01 |
|*  2 |   COUNT STOPKEY     |      |       |       |            |          |
|   3 |    TABLE ACCESS FULL| T1   |    40 |  4000 |     2   (0)| 00:00:01 |
----------------------------------------------------------------------------
Predicate Information (identified by operation id):
---------------------------------------------------
1 - filter("RN">=21)
2 - filter(ROWNUM<=40)
00: 00: 00.030  recursive calls
0  db block gets
6  consistent gets
20  physical reads
0  redo size
1720  bytes sent via SQL*Net to client
431  bytes received via SQL*Net from client
3  SQL*Net roundtrips to/from client
0  sorts (memory)
0  sorts (disk)
20  rows processed
關(guān)聯(lián)查詢
[sql]
--查詢語句1
SELECT * FROM
(
SELECT A.*, ROWNUM RN
FROM (SELECT * FROM T, T1 WHERE T.USERNAME = T1.OWNER) A
WHERE ROWNUM <= 40
)
WHERE RN >= 21;
--查詢語句2
SELECT /*+ FIRST_ROWS */ * FROM
(
SELECT A.*, ROWNUM RN
FROM (SELECT * FROM T, T1 WHERE T.USERNAME = T1.OWNER) A
WHERE ROWNUM <= 40
)
WHERE RN >= 21;
--或者
SELECT * FROM
(
SELECT A.*, ROWNUM RN
FROM (SELECT /*+ USE_NL(T T1) */ * FROM T, T1 WHERE T.USERNAME = T1.OWNER) A
WHERE ROWNUM <= 40
)
WHERE RN >= 21;
可以看到默認是采用hash join,改用nested loop join方式似乎效率并沒有明顯提高,但是這是由于表T比較小只有34行,所以hash join的第一步即使對T進行全表掃描而無法應(yīng)用stopkey,效率也很高。
執(zhí)行計劃執(zhí)行時間統(tǒng)計信息
查詢語句1
-----------------------------------------------------------------------------
| Id  | Operation            | Name | Rows  | Bytes | Cost (%CPU)| Time     |
-----------------------------------------------------------------------------
|   0 | SELECT STATEMENT     |      |    40 |   165K|     6  (17)| 00:00:01 |
|*  1 |  VIEW                |      |    40 |   165K|     6  (17)| 00:00:01 |
|*  2 |   COUNT STOPKEY      |      |       |       |            |          |
|*  3 |    HASH JOIN         |      |    40 | 12400 |     6  (17)| 00:00:01 |
|   4 |     TABLE ACCESS FULL| T    |    34 |  3740 |     3   (0)| 00:00:01 |
|   5 |     TABLE ACCESS FULL| T1   |    40 |  4000 |     2   (0)| 00:00:01 |
-----------------------------------------------------------------------------
Predicate Information (identified by operation id):
---------------------------------------------------
1 - filter("RN">=21)
2 - filter(ROWNUM<=40)
3 - access("T"."USERNAME"="T1"."OWNER")
00: 00: 00.040 recursive calls
0 db block gets
9 consistent gets
20 physical reads
0 redo size
2927 bytes sent via SQL*Net to client
431 bytes received via SQL*Net from client
3 SQL*Net roundtrips to/from client
0 sorts (memory)
0 sorts (disk)
20 rows processed
查詢語句2
-----------------------------------------------------------------------------------------------
| Id  | Operation                      | Name         | Rows  | Bytes | Cost (%CPU)| Time     |
-----------------------------------------------------------------------------------------------
|   0 | SELECT STATEMENT               |              |    40 |   165K| 13627   (1)| 00:02:44 |
|*  1 |  VIEW                          |              |    40 |   165K| 13627   (1)| 00:02:44 |
|*  2 |   COUNT STOPKEY                |              |       |       |            |          |
|   3 |    NESTED LOOPS                |              |       |       |            |          |
|   4 |     NESTED LOOPS               |              |   623K|   124M| 13627   (1)| 00:02:44 |
|   5 |      TABLE ACCESS FULL         | T            |    34 |  3740 |     3   (0)| 00:00:01 |
|*  6 |      INDEX RANGE SCAN          | IND_T1_OWNER | 36684 |       |    91   (0)| 00:00:02 |
|   7 |     TABLE ACCESS BY INDEX ROWID| T1           | 18342 |  1791K|   710   (1)| 00:00:09 |
-----------------------------------------------------------------------------------------------
Predicate Information (identified by operation id):
---------------------------------------------------
1 - filter("RN">=21)
2 - filter(ROWNUM<=40)
6 - access("T"."USERNAME"="T1"."OWNER")
00: 00: 00.011 recursive calls
0 db block gets
14 consistent gets
0 physical reads
0 redo size
2927 bytes sent via SQL*Net to client
431 bytes received via SQL*Net from client
3 SQL*Net roundtrips to/from client
0 sorts (memory)
0 sorts (disk)
20 rows processed
現(xiàn)在增大表T,
[sql]
ALTER TABLE T MODIFY(USER_ID NULL, ACCOUNT_STATUS NULL, DEFAULT_TABLESPACE NULL,
TEMPORARY_TABLESPACE NULL, CREATED NULL, PROFILE NULL);
INSERT INTO T(USERNAME) SELECT ('USER' || LEVEL) FROM DUAL CONNECT BY LEVEL < 100000;
COMMIT;
EXEC DBMS_STATS.GATHER_TABLE_STATS(USER, 'T')
然后重新測試語句1,會發(fā)現(xiàn)現(xiàn)在oracle已經(jīng)改成用nested loop join了。
因此現(xiàn)在語句1和語句2的效果等同了。可以使用 USE_HASH(T T1) HINT強制使用hash join,結(jié)果做下對比,會發(fā)現(xiàn)hash join的效率低于nested loop join,讀數(shù)據(jù)發(fā)生的IO(consistent gets+physical reads)大大增加了.
可以看到CBO是相當智能了。
含排序的查詢
含排序操作的分頁查詢。可以簡單的將查詢分為兩種不同情況,第一種排序列就是索引列,這種可以利用索引讀取,第二種排序列沒有索引。
第一種情況又可以細分為:完全索引掃描和通過索引掃描定位到表記錄兩種情況。無論是那種情況,都可以通過索引的全掃描來避免排序的產(chǎn)生。
第二種情況下,排序不可避免,但是利用給出分頁格式,Oracle不會對所有數(shù)據(jù)進行排序,而是只排序前N條記錄。
[sql]
--查詢語句1,排序列就是索引列.注意這里需要加上OWNER IS NOT NULL,否則由于OWNER列不是NOT NULL,會導致索引無法使用。
SELECT * FROM
(
SELECT A.*, ROWNUM RN
FROM (SELECT * FROM T1 WHERE OWNER IS NOT NULL ORDER BY OWNER) A
WHERE ROWNUM <= 40
)
WHERE RN >= 21;
--查詢語句2,排序列沒有索引
SELECT * FROM
(
SELECT A.*, ROWNUM RN
FROM (SELECT * FROM T1 ORDER BY NAME) A
WHERE ROWNUM <= 40
)
WHERE RN >= 21;
--查詢語句3,排序列沒有索引
SELECT * FROM
(
SELECT A.*, ROWNUM RN
FROM (SELECT * FROM T1 ORDER BY NAME) A
)
WHERE RN BETWEEN 21 AND 40;
執(zhí)行計劃執(zhí)行時間統(tǒng)計信息
查詢語句1
-----------------------------------------------------------------------------------------------
| Id  | Operation                      | Name         | Rows  | Bytes | Cost (%CPU)| Time     |
-----------------------------------------------------------------------------------------------
|   0 | SELECT STATEMENT               |              |    40 | 82800 |     4   (0)| 00:00:01 |
|*  1 |  VIEW                          |              |    40 | 82800 |     4   (0)| 00:00:01 |
|*  2 |   COUNT STOPKEY                |              |       |       |            |          |
|   3 |    VIEW                        |              |    40 | 82280 |     4   (0)| 00:00:01 |
|   4 |     TABLE ACCESS BY INDEX ROWID| T1           |   646K|    62M|     4   (0)| 00:00:01 |
|*  5 |      INDEX FULL SCAN           | IND_T1_OWNER |    40 |       |     3   (0)| 00:00:01 |
-----------------------------------------------------------------------------------------------
Predicate Information (identified by operation id):
---------------------------------------------------
1 - filter("RN">=21)
2 - filter(ROWNUM<=40)
5 - filter("OWNER" IS NOT NULL)
*排序列就是索引列,可以看到通過索引的全掃描來避免了排序的產(chǎn)生。00: 00: 00.011 recursive calls
0 db block gets
8 consistent gets
1 physical reads
0 redo size
1682 bytes sent via SQL*Net to client
427 bytes received via SQL*Net from client
3 SQL*Net roundtrips to/from client
0 sorts (memory)
0 sorts (disk)
20 rows processed
查詢語句2
-----------------------------------------------------------------------------------------
| Id  | Operation                | Name | Rows  | Bytes |TempSpc| Cost (%CPU)| Time     |
-----------------------------------------------------------------------------------------
|   0 | SELECT STATEMENT         |      |    40 | 82800 |       | 18077   (1)| 00:03:37 |
|*  1 |  VIEW                    |      |    40 | 82800 |       | 18077   (1)| 00:03:37 |
|*  2 |   COUNT STOPKEY          |      |       |       |       |            |          |
|   3 |    VIEW                  |      |   646K|  1268M|       | 18077   (1)| 00:03:37 |
|*  4 |     SORT ORDER BY STOPKEY|      |   646K|    62M|    72M| 18077   (1)| 00:03:37 |
|   5 |      TABLE ACCESS FULL   | T1   |   646K|    62M|       |  3023   (1)| 00:00:37 |
-----------------------------------------------------------------------------------------
Predicate Information (identified by operation id):
---------------------------------------------------
1 - filter("RN">=21)
2 - filter(ROWNUM<=40)
4 - filter(ROWNUM<=40)
*排序列沒有索引,排序不可避免。帶STOPKEY的ORDER BY,排序操作放到了內(nèi)存中,
在大數(shù)據(jù)量需要排序的情況下,要比不帶STOPKEY排序的效率高得多。
00: 00: 01.321 recursive calls
0 db block gets
10973 consistent gets
10969 physical reads
0 redo size
2529 bytes sent via SQL*Net to client
427 bytes received via SQL*Net from client
3 SQL*Net roundtrips to/from client
1 sorts (memory)
0 sorts (disk)
20 rows processed
查詢語句3
--------------------------------------------------------------------------------------
| Id  | Operation             | Name | Rows  | Bytes |TempSpc| Cost (%CPU)| Time     |
--------------------------------------------------------------------------------------
|   0 | SELECT STATEMENT      |      |   646K|  1276M|       | 18077   (1)| 00:03:37 |
|*  1 |  VIEW                 |      |   646K|  1276M|       | 18077   (1)| 00:03:37 |
|   2 |   COUNT               |      |       |       |       |            |          |
|   3 |    VIEW               |      |   646K|  1268M|       | 18077   (1)| 00:03:37 |
|   4 |     SORT ORDER BY     |      |   646K|    62M|    72M| 18077   (1)| 00:03:37 |
|   5 |      TABLE ACCESS FULL| T1   |   646K|    62M|       |  3023   (1)| 00:00:37 |
--------------------------------------------------------------------------------------
Predicate Information (identified by operation id):
---------------------------------------------------
1 - filter("RN"<=40 AND "RN">=21)
*排序列沒有索引,排序不可避免,不帶STOPKEY,
進行的數(shù)據(jù)的全排序,排序數(shù)據(jù)量大,排序操作不得不在磁盤上完成,因此耗時比較多。
00: 00: 05.3172 recursive calls
26 db block gets
10973 consistent gets
19933 physical reads
0 redo size
6489 bytes sent via SQL*Net to client
427 bytes received via SQL*Net from client
3 SQL*Net roundtrips to/from client
0 sorts (memory)
1 sorts (disk)
20 rows processed
排序列不唯一所帶來的問題
[sql]
tony@ORCL1> CREATE TABLE TEST AS SELECT ROWNUM ID, A.* FROM DBA_OBJECTS A;
Table created.
tony@ORCL1> EXEC DBMS_STATS.GATHER_TABLE_STATS(USER, 'TEST');
PL/SQL procedure successfully completed.
tony@ORCL1> COLUMN OBJECT_NAME FORMAT A30
tony@ORCL1> SELECT * FROM
2  (
3  SELECT A.*, ROWNUM RN
4  FROM (SELECT ID, OWNER, OBJECT_NAME FROM TEST WHERE OWNER IS NOT NULL ORDER BY OWNER) A
5  WHERE ROWNUM <= 10
6  )
7  WHERE RN >= 1;
ID OWNER                          OBJECT_NAME                            RN
---------- ------------------------------ ------------------------------ ----------
69170 APEX_030200                    WWV_FLOW_INIT_HTP_BUFFER                1
69179 APEX_030200                    WWV_HTF                                 2
69178 APEX_030200                    WWV_FLOW_LANG                           3
69177 APEX_030200                    WWV_FLOW_UTILITIES                      4
69176 APEX_030200                    VC4000ARRAY                             5
69175 APEX_030200                    WWV_FLOW_SECURITY                       6
69174 APEX_030200                    WWV_FLOW                                7
69173 APEX_030200                    HTMLDB_ITEM                             8
69172 APEX_030200                    WWV_FLOW_GLOBAL                         9
69171 APEX_030200                    WWV_FLOW_IMAGE_PREFIX                  10
10 rows selected.
tony@ORCL1> SELECT * FROM
2  (
3  SELECT A.*, ROWNUM RN
4  FROM (SELECT ID, OWNER, OBJECT_NAME FROM TEST WHERE OWNER IS NOT NULL ORDER BY OWNER) A
5  WHERE ROWNUM <= 20
6  )
7  WHERE RN >= 11;
ID OWNER                          OBJECT_NAME                            RN
---------- ------------------------------ ------------------------------ ----------
69180 APEX_030200                    WWV_HTP                                11
69179 APEX_030200                    WWV_HTF                                12
69178 APEX_030200                    WWV_FLOW_LANG                          13
69177 APEX_030200                    WWV_FLOW_UTILITIES                     14
69176 APEX_030200                    VC4000ARRAY                            15
69175 APEX_030200                    WWV_FLOW_SECURITY                      16
69174 APEX_030200                    WWV_FLOW                               17
69173 APEX_030200                    HTMLDB_ITEM                            18
69172 APEX_030200                    WWV_FLOW_GLOBAL                        19
69171 APEX_030200                    WWV_FLOW_IMAGE_PREFIX                  20
10 rows selected.
--可以看到,有多個ID在兩次查詢中都出現(xiàn)了。
--通過加上ID作為排序列解決這個問題。
tony@ORCL1> SELECT * FROM
2  (
3  SELECT A.*, ROWNUM RN
4  FROM (SELECT ID, OWNER, OBJECT_NAME FROM TEST WHERE OWNER IS NOT NULL ORDER BY OWNER, ID) A
5  WHERE ROWNUM <= 10
6  )
7  WHERE RN >= 1;
ID OWNER                          OBJECT_NAME                            RN
---------- ------------------------------ ------------------------------ ----------
69170 APEX_030200                    WWV_FLOW_INIT_HTP_BUFFER                1
69171 APEX_030200                    WWV_FLOW_IMAGE_PREFIX                   2
69172 APEX_030200                    WWV_FLOW_GLOBAL                         3
69173 APEX_030200                    HTMLDB_ITEM                             4
69174 APEX_030200                    WWV_FLOW                                5
69175 APEX_030200                    WWV_FLOW_SECURITY                       6
69176 APEX_030200                    VC4000ARRAY                             7
69177 APEX_030200                    WWV_FLOW_UTILITIES                      8
69178 APEX_030200                    WWV_FLOW_LANG                           9
69179 APEX_030200                    WWV_HTF                                10
10 rows selected.
tony@ORCL1> SELECT * FROM
2  (
3  SELECT A.*, ROWNUM RN
4  FROM (SELECT ID, OWNER, OBJECT_NAME FROM TEST WHERE OWNER IS NOT NULL ORDER BY OWNER, ID) A
5  WHERE ROWNUM <= 20
6  )
7  WHERE RN >= 11;
ID OWNER                          OBJECT_NAME                            RN
---------- ------------------------------ ------------------------------ ----------
69180 APEX_030200                    WWV_HTP                                11
69181 APEX_030200                    ESCAPE_SC                              12
69182 APEX_030200                    WWV_FLOW_META_DATA                     13
69183 APEX_030200                    WWV_FLOW_TEMPLATES_UTIL                14
69184 APEX_030200                    WWV_RENDER_CALENDAR2                   15
69185 APEX_030200                    WWV_RENDER_CHART2                      16
69186 APEX_030200                    WWV_FLOW_CHECK                         17
69187 APEX_030200                    WWV_RENDER_REPORT3                     18
69188 APEX_030200                    WWV_FLOW_PAGE_CACHE_API                19
69189 APEX_030200                    WWV_FLOW_RENDER_QUERY                  20
10 rows selected.
本站僅提供存儲服務(wù),所有內(nèi)容均由用戶發(fā)布,如發(fā)現(xiàn)有害或侵權(quán)內(nèi)容,請點擊舉報
打開APP,閱讀全文并永久保存 查看更多類似文章
猜你喜歡
類似文章
ORACLE分頁查詢SQL語法——最高效的分頁
Oracle分頁查詢語句
yangtingkun : Oracle分頁查詢語句(六)
仿Orm 自動生成分頁SQL
深入剖析-關(guān)于分頁語句的性能優(yōu)化
Oracle分頁查詢的優(yōu)化方案
更多類似文章 >>
生活服務(wù)
分享 收藏 導長圖 關(guān)注 下載文章
綁定賬號成功
后續(xù)可登錄賬號暢享VIP特權(quán)!
如果VIP功能使用有故障,
可點擊這里聯(lián)系客服!

聯(lián)系客服

主站蜘蛛池模板: 德州市| 清徐县| 海阳市| 文成县| 根河市| 连云港市| 昂仁县| 晴隆县| 乌兰浩特市| 锡林郭勒盟| 通州区| 平罗县| 泰安市| 易门县| 武安市| 巴林左旗| 谷城县| 从江县| 陆川县| 青海省| 甘孜| 阿荣旗| 安康市| 轮台县| 延庆县| 黄平县| 十堰市| 卢氏县| 随州市| 双辽市| 新巴尔虎左旗| 铁岭市| 武川县| 广灵县| 甘谷县| 永清县| 宁河县| 清苑县| 宜州市| 邵阳县| 宣化县|