1、 問題
以下的例子如何優化呢?
SELECT * FROM(SELECT INNER_TABLE.*, ROWNUM OUTER_TABLE_ROWNUM FROM (SELECT t1.* FROM ( SELECT * FROM T1 ) t1 WHERE 1 = 1 ORDER BY T1.TTIME DESC)INNER_TABLE ) OUTER_TABLE WHERE OUTER_TABLE_ROWNUM<=25AND OUTER_TABLE_ROWNUM >0
這個語句是單表全表查詢排序后分頁獲取數據,似乎看起來沒什么優化空間。分頁獲取前25行數據,相當于從按ttime排序后,從這批有序的數據中獲取前25行數據,這里我們可以想到索引是有序的,而要提前獲取數據,在達夢數據庫里需要用到以下兩個參數TOP_ORDER_OPT_FLAG/TOP_ORDER_ESTIMATE_CARD
2、TOP_ORDER_OPT_FLAG/TOP_ORDER_ESTIMATE_CARD
參數 | 參數含義 |
---|---|
TOP_ORDER_OPT_FLAG | 優化帶有 TOP 和 ORDER BY 子句的查詢,使得 SORT 操作符可以省略。優化的效果是盡量使得 ORDER BY 的排序列所對應的基表可以使用包含排序列的索引,從而可以移除排序 SORT 操作符,減少排序操作。如果排序列不屬于同一個基表,或者排序列不是基表列,則無法進行優化。0:不啟用該優化; 1:對最優索引進行優化; 2:優先選擇與排序列一致的可以消除排序的索引進行優化 |
TOP_ORDER_ESTIMATE_CARD | TOP_ORDER_OPT_FLAG=1/2 命中優化時,設置葉子節點的預估掃描行數。下層操作符不是簡單的BT時,如果優化器預估行數不準,可幫助優化器調整,以便選擇最優計劃。默認300。 |
以上摘自《達夢數據庫管理員手冊》
接下來我們來看看其優化效果
首先我們創建order by中列的索引
CREATE OR REPLACE INDEX "IDX_DM_T1" ON "T1"("TTIME" DESC)global;
然后我們使用hint看看其效果
SELECT /*+TOP_ORDER_OPT_FLAG(2)*/* FROM(SELECT INNER_TABLE.*, ROWNUM OUTER_TABLE_ROWNUM FROM (SELECT t1.* FROM ( SELECT * FROM T1 ) t1 WHERE 1 = 1 ORDER BY T1.TTIME DESC)INNER_TABLE ) OUTER_TABLE WHERE OUTER_TABLE_ROWNUM<=25AND OUTER_TABLE_ROWNUM >0
這里提前獲取300行數據,然后再分頁取得25行,300也就是TOP_ORDER_ESTIMATE_CARD的配置。
3、小結
假設單表大表排序分頁提前獲取前幾十行數據。通過增加排序列索引加上top_order_opt_flag=2即可達到優化效果。