2015年5月20日19:14:43 - 排序sql
實際排序所用到的內存、磁盤的統計信息:session
pga_aggregate_target:此參數用來指定全部session總計可使用最大PGA內存 olap:50% oltp:20%oracle
sqlSQL> show parameter pga_aggre NAME TYPE VALUE ------------------------------------ ---------------------- ------------------------------ pga_aggregate_target big integer 0 SQL> show parameter workarea_size_policy
workarea_size_policy:此參數用於開關PGA內存自動管理功能 auto:自動分配sort_area_size 屬於workarea 若是須要常常排序就須要把這個值設置大點ide
sqlSQL> show parameter workarea_size_policy NAME TYPE VALUE ------------------------------------ ---------------------- ------------------------------ workarea_size_policy string AUTO
select name, value from v$sysstat where name like ‘sort%’; select * from v$pgastat;性能
sqlSQL> select name , value from v$sysstat where name like 'sort%'; NAME VALUE -------------------------------------------------------------------------------------------------------------------------------- ---------- sorts (memory) 4283 sorts (disk) 0 sorts (rows) 40823
select * from customers;this
sqlSQL> set autotrace traceonly SQL> select * from customers; 已選擇55500行。 已用時間: 00: 00: 01.93 執行計劃 ---------------------------------------------------------- Plan hash value: 2008213504 ------------------------------------------------------------------------------- | Id | Operation | Name | Rows | Bytes | Cost (%CPU)| Time | ------------------------------------------------------------------------------- | 0 | SELECT STATEMENT | | 55500 | 9810K| 406 (1)| 00:00:05 | | 1 | TABLE ACCESS FULL| CUSTOMERS | 55500 | 9810K| 406 (1)| 00:00:05 | ------------------------------------------------------------------------------- 統計信息 ---------------------------------------------------------- 1 recursive calls 0 db block gets 5057 consistent gets 1455 physical reads 0 redo size 10855625 bytes sent via SQL*Net to client 41109 bytes received via SQL*Net from client 3701 SQL*Net roundtrips to/from client 0 sorts (memory) 0 sorts (disk) 55500 rows processed
select * from customers order by cust_last_name;code
sqlSQL> select * from customers order by cust_last_name; 已選擇55500行。 已用時間: 00: 00: 01.93 執行計劃 ---------------------------------------------------------- Plan hash value: 2792773903 ---------------------------------------------------------------------------------------- | Id | Operation | Name | Rows | Bytes |TempSpc| Cost (%CPU)| Time | ---------------------------------------------------------------------------------------- | 0 | SELECT STATEMENT | | 55500 | 9810K| | 2612 (1)| 00:00:32 | | 1 | SORT ORDER BY | | 55500 | 9810K| 12M| 2612 (1)| 00:00:32 | | 2 | TABLE ACCESS FULL| CUSTOMERS | 55500 | 9810K| | 406 (1)| 00:00:05 | ---------------------------------------------------------------------------------------- 統計信息 ---------------------------------------------------------- 1 recursive calls 0 db block gets 1459 consistent gets 1454 physical reads 0 redo size 6278979 bytes sent via SQL*Net to client 41109 bytes received via SQL*Net from client 3701 SQL*Net roundtrips to/from client 1 sorts (memory) 0 sorts (disk) 55500 rows processed
能夠看到使用order by
用到了額外的12M內存orm
沒建索引:排序
sqlexplain plan for select cust_last_name from customers order by cust_last_name;
sqlSQL> select * from table(dbms_xplan.display); PLAN_TABLE_OUTPUT ------------------------------------------------------------------------------------------------------------------ Plan hash value: 2792773903 ---------------------------------------------------------------------------------------- | Id | Operation | Name | Rows | Bytes |TempSpc| Cost (%CPU)| Time | ---------------------------------------------------------------------------------------- | 0 | SELECT STATEMENT | | 55500 | 433K| | 610 (1)| 00:00:08 | | 1 | SORT ORDER BY | | 55500 | 433K| 880K| 610 (1)| 00:00:08 | | 2 | TABLE ACCESS FULL| CUSTOMERS | 55500 | 433K| | 405 (1)| 00:00:05 | ----------------------------------------------------------------------------------------
創建索引:索引
sqlcreate index lastname_idx on customers(cust_last_name);
sqlexplain plan for select /*+ index(c lastname_idx) */ cust_last_name from customers order by cust_last_name;
執行計劃:
sqlSQL> explain plan for select /*+ index(c lastname_idx) */ cust_last_name from customers order by cust_last_name; 已解釋。 已用時間: 00: 00: 00.00 SQL> select * from table(dbms_xplan.display); PLAN_TABLE_OUTPUT ------------------------------------------------------------------------------------------------------------------ Plan hash value: 3470560620 --------------------------------------------------------------------------------- | Id | Operation | Name | Rows | Bytes | Cost (%CPU)| Time | --------------------------------------------------------------------------------- | 0 | SELECT STATEMENT | | 55500 | 433K| 143 (1)| 00:00:02 | | 1 | INDEX FULL SCAN | LASTNAME_IDX | 55500 | 433K| 143 (1)| 00:00:02 | ---------------------------------------------------------------------------------
能夠發如今一列創建索引後,對該列進行排序操做不須要再執行排序操做,
他會根據索引來進行查詢(索引中原本就已經排好序)
創建索引能夠節省排序操做的時間。
一般咱們都會:
sqlselect cust_last_name from customers where rownum<=20 order by 1;
sqlSQL> select cust_last_name from customers where rownum<=20 order by 1; CUST_LAST_NAME -------------------------------------------------------------------------------- Everett Everett Everett Everett Everett Everett Everett Everett Everett Ruddy Ruddy CUST_LAST_NAME -------------------------------------------------------------------------------- Ruddy Ruddy Ruddy Ruddy Ruddy Ruddy Ruddy Ruddy Ruddy 已選擇20行。
這樣是錯誤的,由於在oracle中where永遠都是先執行的也就先取20條再排序。
正確的作法是使用子查詢:
sqlselect cust_last_name from (select * from customers order by cust_last_name) where rownum<10;
sqlSQL>select cust_last_name from (select * from customers order by cust_last_name) where rownum<10; CUST_LAST_NAME -------------------------------------------------------------------------------- Aaron Aaron Aaron Aaron Aaron Aaron Aaron Aaron Aaron Aaron Aaron CUST_LAST_NAME -------------------------------------------------------------------------------- Aaron Aaron Aaron Aaron Aaron Aaron Aaron Aaron Aaron 已選擇20行。
沒建索引:
sqlPLAN_TABLE_OUTPUT -------------------------------------------------------------------------------------------------------- Plan hash value: 1285511559 --------------------------------------------------------------------------------------------- | Id | Operation | Name | Rows | Bytes |TempSpc| Cost (%CPU)| Time | --------------------------------------------------------------------------------------------- | 0 | SELECT STATEMENT | | 9 | 198 | | 2612 (1)| 00:00:32 | |* 1 | COUNT STOPKEY | | | | | | | | 2 | VIEW | | 55500 | 1192K| | 2612 (1)| 00:00:32 | |* 3 | SORT ORDER BY STOPKEY| | 55500 | 9810K| 12M| 2612 (1)| 00:00:32 | | 4 | TABLE ACCESS FULL | CUSTOMERS | 55500 | 9810K| | 406 (1)| 00:00:05 | --------------------------------------------------------------------------------------------- PLAN_TABLE_OUTPUT -------------------------------------------------------------------------------------------------------- Predicate Information (identified by operation id): --------------------------------------------------- 1 - filter(ROWNUM<10) 3 - filter(ROWNUM<10) 已選擇17行。
創建索引後:
sqlPLAN_TABLE_OUTPUT ---------------------------------------------------------------------------------------------------- Plan hash value: 3026242074 ---------------------------------------------------------------------------------- | Id | Operation | Name | Rows | Bytes | Cost (%CPU)| Time | ---------------------------------------------------------------------------------- | 0 | SELECT STATEMENT | | 9 | 198 | 4 (0)| 00:00:01 | |* 1 | COUNT STOPKEY | | | | | | | 2 | VIEW | | 9 | 198 | 4 (0)| 00:00:01 | | 3 | INDEX FULL SCAN| LASTNAME_IDX | 9 | | 2 (0)| 00:00:01 | ---------------------------------------------------------------------------------- PLAN_TABLE_OUTPUT ---------------------------------------------------------------------------------------------------- Predicate Information (identified by operation id): --------------------------------------------------- 1 - filter(ROWNUM<10) 已選擇15行。
創建索引後,子查詢效率明顯提升
同時select cust_last_name from customers where rownum<=10 order by cust_last_name;
和上面的結果已經大不相同。
sqlSQL> select cust_last_name from customers where rownum<=10 order by cust_last_name; CUST_LAST_NAME -------------------------------------------------------------------------------- Aaron Aaron Aaron Aaron Aaron Aaron Aaron Aaron Aaron Aaron 已選擇10行。
執行計劃:
sqlSQL> explain plan for 2 select cust_last_name from customers where rownum<=10 order by cust_last_name; 已解釋。 已用時間: 00: 00: 00.00 SQL> select * from table(dbms_xplan.display); PLAN_TABLE_OUTPUT --------------------------------------------------------------------------------------------- Plan hash value: 2820001957 --------------------------------------------------------------------------------- | Id | Operation | Name | Rows | Bytes | Cost (%CPU)| Time | --------------------------------------------------------------------------------- | 0 | SELECT STATEMENT | | 10 | 80 | 2 (0)| 00:00:01 | |* 1 | COUNT STOPKEY | | | | | | | 2 | INDEX FULL SCAN| LASTNAME_IDX | 55500 | 433K| 2 (0)| 00:00:01 | --------------------------------------------------------------------------------- Predicate Information (identified by operation id): PLAN_TABLE_OUTPUT --------------------------------------------------------------------------------------------- --------------------------------------------------- 1 - filter(ROWNUM<=10) 已選擇14行。
居然不是剛剛那樣亂的。
創建索引可以對提升子查詢的性能,而且查詢前十條記錄再也不須要使用子查詢, 由於創建好索引後已是排好序的,只要根據索引從表中拿出前十條記錄便可。
首先先創建一個表
sqlSQL> create table s as select * from sales; 表已建立。
s表與sales表的數據徹底是一致的但s表沒有sales表上的索引。
而後咱們看一下執行計劃:
sqlSQL> explain plan for 2 select cust_id,avg(amount_sold) from s group by cust_id; 已解釋。 已用時間: 00: 00: 00.23 SQL> select * from table(dbms_xplan.display); PLAN_TABLE_OUTPUT ------------------------------------------------------------------------------------ Plan hash value: 1912481676 --------------------------------------------------------------------------- | Id | Operation | Name | Rows | Bytes | Cost (%CPU)| Time | --------------------------------------------------------------------------- | 0 | SELECT STATEMENT | | 785K| 19M| 1271 (4)| 00:00:16 | | 1 | HASH GROUP BY | | 785K| 19M| 1271 (4)| 00:00:16 | | 2 | TABLE ACCESS FULL| S | 785K| 19M| 1236 (1)| 00:00:15 | --------------------------------------------------------------------------- Note PLAN_TABLE_OUTPUT ------------------------------------------------------------------------------------ ----- - dynamic sampling used for this statement (level=2) 已選擇13行。
咱們再看一下sales表(即創建了索引的表):
sqlSQL> select * from table(dbms_xplan.display); PLAN_TABLE_OUTPUT -------------------------------------------------------------------------------------- Plan hash value: 2820001957 --------------------------------------------------------------------------------- | Id | Operation | Name | Rows | Bytes | Cost (%CPU)| Time | --------------------------------------------------------------------------------- | 0 | SELECT STATEMENT | | 10 | 80 | 2 (0)| 00:00:01 | |* 1 | COUNT STOPKEY | | | | | | | 2 | INDEX FULL SCAN| LASTNAME_IDX | 55500 | 433K| 2 (0)| 00:00:01 | --------------------------------------------------------------------------------- Predicate Information (identified by operation id): PLAN_TABLE_OUTPUT -------------------------------------------------------------------------------------- --------------------------------------------------- 1 - filter(ROWNUM<=10) 已選擇14行。
group by
的一列上創建索引group by 性能更佳。
下面是關於order by 升序降序的執行計劃能夠看出創建索引升降序對排序不會影響性能
升序:
sqlSQL> select cust_last_name from customers where rownum <= 10 order by cust_last_name; SQL> select * from table(dbms_xplan.display); PLAN_TABLE_OUTPUT -------------------------------------------------------------------------------------- Plan hash value: 2820001957 --------------------------------------------------------------------------------- | Id | Operation | Name | Rows | Bytes | Cost (%CPU)| Time | --------------------------------------------------------------------------------- | 0 | SELECT STATEMENT | | 10 | 80 | 2 (0)| 00:00:01 | |* 1 | COUNT STOPKEY | | | | | | | 2 | INDEX FULL SCAN| LASTNAME_IDX | 55500 | 433K| 2 (0)| 00:00:01 | --------------------------------------------------------------------------------- Predicate Information (identified by operation id): PLAN_TABLE_OUTPUT -------------------------------------------------------------------------------------- --------------------------------------------------- 1 - filter(ROWNUM<=10) 已選擇14行。
降序:
sqlSQL> select cust_last_name from customers where rownum <= 10 order by cust_last_name; SQL> select * from table(dbms_xplan.display); PLAN_TABLE_OUTPUT -------------------------------------------------------------------------------------------------- Plan hash value: 1596600344 -------------------------------------------------------------------------------------------- | Id | Operation | Name | Rows | Bytes | Cost (%CPU)| Time | -------------------------------------------------------------------------------------------- | 0 | SELECT STATEMENT | | 9 | 72 | 2 (0)| 00:00:01 | |* 1 | COUNT STOPKEY | | | | | | | 2 | INDEX FULL SCAN DESCENDING| LASTNAME_IDX | 55500 | 433K| 2 (0)| 00:00:01 | -------------------------------------------------------------------------------------------- Predicate Information (identified by operation id): PLAN_TABLE_OUTPUT -------------------------------------------------------------------------------------------------- --------------------------------------------------- 1 - filter(ROWNUM<10) 已選擇14行。