一條sql語句的改進探索
昨天同事找我,讓我幫忙看兩個sql問題,第一個問題是一個sql語句執行頻率極高,但是目前的執行速度還是比較慢,希望我看看能不能調優一下。
另外一個問題是一個查詢執行速度比較慢,但是執行頻率不高。
我們還是循序漸進,一個一個來看。
第一個sql語句如下
5knr1ywqugtq8
/* TransactionLog_selectByAccRangeTrx_3 */
SELECT TRANSACTION_LOG.TRANS_DATE,
TRANSACTION_LOG.TRANS_TYPE,
TRANSACTION_LOG.PARTITION_ID,
TRANSACTION_LOG.ACCOUNT_ID,
TRANSACTION_LOG.TRANSACTION_ID,
TRANSACTION_LOG.SUB_TRANSACTION_ID,
TRANSACTION_LOG.SYS_UPDATE_DATE,
TRANSACTION_LOG.SYS_CREATION_DATE,
TRANSACTION_LOG.DL_SERVICE_CODE,
TRANSACTION_LOG.APPLICATION_ID,
TRANSACTION_LOG.DL_UPDATE_STAMP,
TRANSACTION_LOG.OPERATOR_ID,
TRANSACTION_LOG.PERIOD_KEY,
TRANSACTION_LOG.ENTITY_PERIOD_KEY
FROM TRANSACTION_LOG
WHERE TRANSACTION_LOG.ACCOUNT_ID = :1
AND TRANSACTION_LOG.PARTITION_ID = :2
AND TRANSACTION_LOG.TRANSACTION_ID >= :3
AND TRANSACTION_LOG.TRANSACTION_ID <= :4
AND TRANSACTION_LOG.TRANS_TYPE IN
(SELECT /*+ cardinality(1)*/
DISTINCT column_value as transType
FROM table (SELECT CAST(:5 AS ar1_ Varchar2Array_tp) FROM DUAL))
執行計劃如下,從執行計劃來看,看起來執行計劃還是不錯的。索引也使用到了,而且消耗也不高。
Plan hash value: 88692238
----------------------------------------------------------------------------------------------------------------------------------
| Id | Operation | Name | Rows | Bytes | Cost (%CPU)| Time | Pstart| Pstop |
----------------------------------------------------------------------------------------------------------------------------------
| 0 | SELECT STATEMENT | | | | 93 (100)| | | |
| 1 | NESTED LOOPS | | | | | | | |
| 2 | NESTED LOOPS | | 1 | 81 | 93 (2)| 00:00:02 | | |
| 3 | VIEW | VW_NSO_1 | 1 | 12 | 19 (0)| 00:00:01 | | |
| 4 | HASH UNIQUE | | 1 | 2 | | | | |
|* 5 | FILTER | | | | | | | |
| 6 | COLLECTION ITERATOR PICKLER FETCH| | 8168 | 16336 | 19 (0)| 00:00:01 | | |
| 7 | FAST DUAL | | 1 | | 2 (0)| 00:00:01 | | |
| 8 | PARTITION RANGE MULTI-COLUMN | | 7 | | 73 (0)| 00:00:01 |KEY(MC)|KEY(MC)|
|* 9 | INDEX RANGE SCAN | TRANSACTION_LOG_2IX | 7 | | 73 (0)| 00:00:01 |KEY(MC)|KEY(MC)|
|* 10 | TABLE ACCESS BY LOCAL INDEX ROWID | TRANSACTION_LOG | 1 | 69 | 73 (0)| 00:00:01 | 1 | 1 |
----------------------------------------------------------------------------------------------------------------------------------
索引情況如下:
INDEX_NAME INDEX_TYPE UNIQUENES PAR COLUMN_LIST TABLE_TYPE STATUS NUM_ROWS LAST_ANAL G
------------------------------ ---------- --------- --- ------------------------------ ---------- ------ ---------- --------- -
TRANSACTION_LOG_1IX NORMAL NONUNIQUE YES TRANSACTION_ID,TRANS_TYPE TABLE N/A 270774323 01-APR-15 N
TRANSACTION_LOG_2IX NORMAL NONUNIQUE YES ACCOUNT_ID,TRANS_TYPE TABLE N/A 270776953 01-APR-15 N
TRANSACTION_LOG_PK NORMAL UNIQUE YES SUB_TRANSACTION_ID,PARTITION_ID,PERIOD_KEY TABLE N/A 270772197 01-APR-15 N
可以看到索引還是用了TRANSACTION_LOG_2IX,即使用了欄位ACCOUNT_ID,TRANS_TYPE來進行資料過濾。
從sql語句的執行和資料分佈來看,還是合理的,沒有什麼問題。根據現在的執行情況,每次執行大約需要2秒以上。期望還是能夠達到1秒以內甚至更低。
我們來看看索引TRANSACTION_LOG_1IX和TRANSACTION_LOG_2IX,其實會發現無論是使用第一個還是第二個,資料的分佈還是基本平均的。
從叢集因子也能看出。
TABLE_NAME INDEX_NAME CLUSTERING_FACTOR BLOCKS NUM_ROWS
----------------- -- -------------------- ----------------- ---------- ----------
TRANSACTION_LOG TRANSACTION_LOG_1IX 183188039 2912269 270768896
TRANSACTION_LOG TRANSACTION_LOG_2IX 237869001 2912269 270768896
TRANSACTION_LOG TRANSACTION_LOG_PK 186148006 2912269 270768896
不過多多少少還是有些差別的。不過差別還是不大,我們還是用sql profile來看看能夠給點什麼建議。
很快生成了報告,可以看出,改進其實不大。大約只有不到20%的改進。
Original Plan With SQL Profile % Improved
------------- ---------------- ----------
Completion Status: COMPLETE COMPLETE
Elapsed Time (s): .000389 .00033 15.16 %
CPU Time (s): .000399 .000299 25.06 %
User I/O Time (s): 0 0
Buffer Gets: 0 0
Physical Read Requests: 0 0
Physical Write Requests: 0 0
Physical Read Bytes: 0 0
Physical Write Bytes: 0 0
Rows Processed: 0 0
Fetches: 0 0
Executions: 1 1
而且從改進的執行計劃來看,其實主要的差別就在於索引掃描了。索引掃描從原來的range scan建議改為skip scan.
2- Using SQL Profile
--------------------
Plan hash value: 1415584969
---------------------------------------------------------------------------------------------------------------------------------
| Id | Operation | Name | Rows | Bytes | Cost (%CPU)| Time | Pstart| Pstop |
---------------------------------------------------------------------------------------------------------------------------------
| 0 | SELECT STATEMENT | | 1 | 81 | 93 (2)| 00:00:02 | | |
| 1 | NESTED LOOPS | | 1 | 81 | 93 (2)| 00:00:02 | | |
| 2 | VIEW | VW_NSO_1 | 8168 | 98016 | 19 (0)| 00:00:01 | | |
| 3 | HASH UNIQUE | | 1 | 16336 | | | | |
|* 4 | FILTER | | | | | | | |
| 5 | COLLECTION ITERATOR PICKLER FETCH| | 8168 | 16336 | 19 (0)| 00:00:01 | | |
| 6 | FAST DUAL | | 1 | | 2 (0)| 00:00:01 | | |
| 7 | PARTITION RANGE MULTI-COLUMN | | 1 | 69 | 73 (0)| 00:00:01 |KEY(MC)|KEY(MC)|
|* 8 | TABLE ACCESS BY LOCAL INDEX ROWID | AR1_TRANSACTION_LOG | 1 | 69 | 73 (0)| 00:00:01 |KEY(MC)|KEY(MC)|
|* 9 | INDEX SKIP SCAN | AR1_TRANSACTION_LOG_1IX | 1 | | 73 (0)| 00:00:01 |KEY(MC)|KEY(MC)|
---------------------------------------------------------------------------------------------------------------------------------
NAME TYPE VALUE
------------------------------------ ----------- ------------------------------
_optimizer_skip_scan_enabled boolean FALSE
不過對此,也不是沒有辦法,可以使用opt_param來啟用,使用hint的例項如下:
/*+opt_param('_optimizer_skip_scan_enabled', 'true')*/
不過雖然可行,但是不一定我們需要確實值得這麼去做。我們還是需要評估一下。
首先skip scan在一些場景中已經碰到了一些相關的問題,不能直接根據執行計劃的情況進行調優。執行計劃可以作為參考,但不是全部。
二來目前的執行情況來看,就算啟用skip scan,收效也不大,提高20%左右儘管在1秒以上,但是還是存在問題。
三來從這個語句來看,這個查詢其實還是一個很簡單的語句,沒有關聯表,使用了索引,查詢條件也不復雜,調優的空間確實有限。就算退一步來看看使用另外一個索引,其實改進空間也是不大的。
這個可以簡單的測試證明,這個查詢沒有使用transaction_id相關的索引列,其實很大一部分就是因為>=, <=的原因。
我們可以模擬測試一下,把<=改為=改為>= 得到的執行計劃就會是下面的樣子
----------------------------------------------------------------------------------------------------------------------------------
| Id | Operation | Name | Rows | Bytes | Cost (%CPU)| Time | Pstart| Pstop |
----------------------------------------------------------------------------------------------------------------------------------
| 0 | SELECT STATEMENT | | 1 | 81 | 93 (2)| 00:00:02 | | |
| 1 | NESTED LOOPS | | | | | | | |
| 2 | NESTED LOOPS | | 1 | 81 | 93 (2)| 00:00:02 | | |
| 3 | VIEW | VW_NSO_1 | 1 | 12 | 19 (0)| 00:00:01 | | |
| 4 | HASH UNIQUE | | 1 | 2 | | | | |
|* 5 | FILTER | | | | | | | |
| 6 | COLLECTION ITERATOR PICKLER FETCH| | 8168 | 16336 | 19 (0)| 00:00:01 | | |
| 7 | FAST DUAL | | 1 | | 2 (0)| 00:00:01 | | |
| 8 | PARTITION RANGE MULTI-COLUMN | | 7 | | 73 (0)| 00:00:01 |KEY(MC)|KEY(MC)|
|* 9 | INDEX RANGE SCAN | TRANSACTION_LOG_2IX | 7 | | 73 (0)| 00:00:01 |KEY(MC)|KEY(MC)|
|* 10 | TABLE ACCESS BY LOCAL INDEX ROWID | TRANSACTION_LOG | 1 | 69 | 73 (0)| 00:00:01 | 1 | 1 |
----------------------------------------------------------------------------------------------------------------------------------
改進空間還是很有限的。
對此我的建議還是能夠從多個方面來考慮。
首先就是索引,目前存在3個索引,其實TRANSACTION_LOG_1IX和TRANSACTION_LOG_2IX都是非唯一性索引,如果能夠使用TRANSACTION_LOG_PK其實還是有很大的改進空間。和開發同事的交流來看,他們認為改動難度較大,需要改動的程式碼量很大,可能需要的時間也較長。但是也不失為一種方式。所以這個方案也是可行但是能不能落地還是一個問號。畢竟在雙方的一個權衡中也需要很多的協調。
第二個改進就是和開發的交流和自己抓取的一些資訊,發現transaction_id的取值範圍還是很大,這也是資料過濾較慢的一個原因。可以從執行計劃的謂詞資訊中看出來一些。首先是根據account_id來進行定位,但是資料過濾是根據transaction_id來做的。做這個時候
9 - access("TRANSACTION_LOG"."ACCOUNT_ID"=:1 AND "TRANSACTION_LOG"."TRANS_TYPE"="TRANSTYPE")
10 - filter(("TRANSACTION_LOG"."TRANSACTION_ID">=:3 AND "TRANSACTION_LOG"."TRANSACTION_ID"<=:4 AND
"TRANSACTION_LOG"."PARTITION_ID"=:2))
所以經過討論一種可行的效果就是能夠不盡可能的縮短transaction_id的範圍。使得transaction_id的範圍儘量小一些,資料過濾就會更加高效。這個從前端來說還是比較容易來實現的。
經過驗證發現速度還是比較理想的,調整了範圍之後,速度都在毫秒。
另外一個問題是一個查詢執行速度比較慢,但是執行頻率不高。
我們還是循序漸進,一個一個來看。
第一個sql語句如下
5knr1ywqugtq8
/* TransactionLog_selectByAccRangeTrx_3 */
SELECT TRANSACTION_LOG.TRANS_DATE,
TRANSACTION_LOG.TRANS_TYPE,
TRANSACTION_LOG.PARTITION_ID,
TRANSACTION_LOG.ACCOUNT_ID,
TRANSACTION_LOG.TRANSACTION_ID,
TRANSACTION_LOG.SUB_TRANSACTION_ID,
TRANSACTION_LOG.SYS_UPDATE_DATE,
TRANSACTION_LOG.SYS_CREATION_DATE,
TRANSACTION_LOG.DL_SERVICE_CODE,
TRANSACTION_LOG.APPLICATION_ID,
TRANSACTION_LOG.DL_UPDATE_STAMP,
TRANSACTION_LOG.OPERATOR_ID,
TRANSACTION_LOG.PERIOD_KEY,
TRANSACTION_LOG.ENTITY_PERIOD_KEY
FROM TRANSACTION_LOG
WHERE TRANSACTION_LOG.ACCOUNT_ID = :1
AND TRANSACTION_LOG.PARTITION_ID = :2
AND TRANSACTION_LOG.TRANSACTION_ID >= :3
AND TRANSACTION_LOG.TRANSACTION_ID <= :4
AND TRANSACTION_LOG.TRANS_TYPE IN
(SELECT /*+ cardinality(1)*/
DISTINCT column_value as transType
FROM table (SELECT CAST(:5 AS ar1_ Varchar2Array_tp) FROM DUAL))
執行計劃如下,從執行計劃來看,看起來執行計劃還是不錯的。索引也使用到了,而且消耗也不高。
Plan hash value: 88692238
----------------------------------------------------------------------------------------------------------------------------------
| Id | Operation | Name | Rows | Bytes | Cost (%CPU)| Time | Pstart| Pstop |
----------------------------------------------------------------------------------------------------------------------------------
| 0 | SELECT STATEMENT | | | | 93 (100)| | | |
| 1 | NESTED LOOPS | | | | | | | |
| 2 | NESTED LOOPS | | 1 | 81 | 93 (2)| 00:00:02 | | |
| 3 | VIEW | VW_NSO_1 | 1 | 12 | 19 (0)| 00:00:01 | | |
| 4 | HASH UNIQUE | | 1 | 2 | | | | |
|* 5 | FILTER | | | | | | | |
| 6 | COLLECTION ITERATOR PICKLER FETCH| | 8168 | 16336 | 19 (0)| 00:00:01 | | |
| 7 | FAST DUAL | | 1 | | 2 (0)| 00:00:01 | | |
| 8 | PARTITION RANGE MULTI-COLUMN | | 7 | | 73 (0)| 00:00:01 |KEY(MC)|KEY(MC)|
|* 9 | INDEX RANGE SCAN | TRANSACTION_LOG_2IX | 7 | | 73 (0)| 00:00:01 |KEY(MC)|KEY(MC)|
|* 10 | TABLE ACCESS BY LOCAL INDEX ROWID | TRANSACTION_LOG | 1 | 69 | 73 (0)| 00:00:01 | 1 | 1 |
----------------------------------------------------------------------------------------------------------------------------------
索引情況如下:
INDEX_NAME INDEX_TYPE UNIQUENES PAR COLUMN_LIST TABLE_TYPE STATUS NUM_ROWS LAST_ANAL G
------------------------------ ---------- --------- --- ------------------------------ ---------- ------ ---------- --------- -
TRANSACTION_LOG_1IX NORMAL NONUNIQUE YES TRANSACTION_ID,TRANS_TYPE TABLE N/A 270774323 01-APR-15 N
TRANSACTION_LOG_2IX NORMAL NONUNIQUE YES ACCOUNT_ID,TRANS_TYPE TABLE N/A 270776953 01-APR-15 N
TRANSACTION_LOG_PK NORMAL UNIQUE YES SUB_TRANSACTION_ID,PARTITION_ID,PERIOD_KEY TABLE N/A 270772197 01-APR-15 N
從sql語句的執行和資料分佈來看,還是合理的,沒有什麼問題。根據現在的執行情況,每次執行大約需要2秒以上。期望還是能夠達到1秒以內甚至更低。
我們來看看索引TRANSACTION_LOG_1IX和TRANSACTION_LOG_2IX,其實會發現無論是使用第一個還是第二個,資料的分佈還是基本平均的。
從叢集因子也能看出。
TABLE_NAME INDEX_NAME CLUSTERING_FACTOR BLOCKS NUM_ROWS
----------------- -- -------------------- ----------------- ---------- ----------
TRANSACTION_LOG TRANSACTION_LOG_1IX 183188039 2912269 270768896
TRANSACTION_LOG TRANSACTION_LOG_2IX 237869001 2912269 270768896
TRANSACTION_LOG TRANSACTION_LOG_PK 186148006 2912269 270768896
不過多多少少還是有些差別的。不過差別還是不大,我們還是用sql profile來看看能夠給點什麼建議。
很快生成了報告,可以看出,改進其實不大。大約只有不到20%的改進。
Original Plan With SQL Profile % Improved
------------- ---------------- ----------
Completion Status: COMPLETE COMPLETE
Elapsed Time (s): .000389 .00033 15.16 %
CPU Time (s): .000399 .000299 25.06 %
User I/O Time (s): 0 0
Buffer Gets: 0 0
Physical Read Requests: 0 0
Physical Write Requests: 0 0
Physical Read Bytes: 0 0
Physical Write Bytes: 0 0
Rows Processed: 0 0
Fetches: 0 0
Executions: 1 1
而且從改進的執行計劃來看,其實主要的差別就在於索引掃描了。索引掃描從原來的range scan建議改為skip scan.
2- Using SQL Profile
--------------------
Plan hash value: 1415584969
---------------------------------------------------------------------------------------------------------------------------------
| Id | Operation | Name | Rows | Bytes | Cost (%CPU)| Time | Pstart| Pstop |
---------------------------------------------------------------------------------------------------------------------------------
| 0 | SELECT STATEMENT | | 1 | 81 | 93 (2)| 00:00:02 | | |
| 1 | NESTED LOOPS | | 1 | 81 | 93 (2)| 00:00:02 | | |
| 2 | VIEW | VW_NSO_1 | 8168 | 98016 | 19 (0)| 00:00:01 | | |
| 3 | HASH UNIQUE | | 1 | 16336 | | | | |
|* 4 | FILTER | | | | | | | |
| 5 | COLLECTION ITERATOR PICKLER FETCH| | 8168 | 16336 | 19 (0)| 00:00:01 | | |
| 6 | FAST DUAL | | 1 | | 2 (0)| 00:00:01 | | |
| 7 | PARTITION RANGE MULTI-COLUMN | | 1 | 69 | 73 (0)| 00:00:01 |KEY(MC)|KEY(MC)|
|* 8 | TABLE ACCESS BY LOCAL INDEX ROWID | AR1_TRANSACTION_LOG | 1 | 69 | 73 (0)| 00:00:01 |KEY(MC)|KEY(MC)|
|* 9 | INDEX SKIP SCAN | AR1_TRANSACTION_LOG_1IX | 1 | | 73 (0)| 00:00:01 |KEY(MC)|KEY(MC)|
---------------------------------------------------------------------------------------------------------------------------------
這個時候,還是很有顧慮的,因為在生產中已經完全能禁用skip scan了,根據產品線的建議是需要禁用的,因為在實際使用中還是碰到了不少的問題,skip scan在有些場景中反而不如range scan,會有full index scan的效果。
所以即使在Hint中知名需要skip scan在生產中也是很可能會走range scan. 在資料庫引數中,禁用skip scan的部分如下:NAME TYPE VALUE
------------------------------------ ----------- ------------------------------
_optimizer_skip_scan_enabled boolean FALSE
不過對此,也不是沒有辦法,可以使用opt_param來啟用,使用hint的例項如下:
/*+opt_param('_optimizer_skip_scan_enabled', 'true')*/
不過雖然可行,但是不一定我們需要確實值得這麼去做。我們還是需要評估一下。
首先skip scan在一些場景中已經碰到了一些相關的問題,不能直接根據執行計劃的情況進行調優。執行計劃可以作為參考,但不是全部。
二來目前的執行情況來看,就算啟用skip scan,收效也不大,提高20%左右儘管在1秒以上,但是還是存在問題。
三來從這個語句來看,這個查詢其實還是一個很簡單的語句,沒有關聯表,使用了索引,查詢條件也不復雜,調優的空間確實有限。就算退一步來看看使用另外一個索引,其實改進空間也是不大的。
這個可以簡單的測試證明,這個查詢沒有使用transaction_id相關的索引列,其實很大一部分就是因為>=, <=的原因。
我們可以模擬測試一下,把<=改為=改為>= 得到的執行計劃就會是下面的樣子
----------------------------------------------------------------------------------------------------------------------------------
| Id | Operation | Name | Rows | Bytes | Cost (%CPU)| Time | Pstart| Pstop |
----------------------------------------------------------------------------------------------------------------------------------
| 0 | SELECT STATEMENT | | 1 | 81 | 93 (2)| 00:00:02 | | |
| 1 | NESTED LOOPS | | | | | | | |
| 2 | NESTED LOOPS | | 1 | 81 | 93 (2)| 00:00:02 | | |
| 3 | VIEW | VW_NSO_1 | 1 | 12 | 19 (0)| 00:00:01 | | |
| 4 | HASH UNIQUE | | 1 | 2 | | | | |
|* 5 | FILTER | | | | | | | |
| 6 | COLLECTION ITERATOR PICKLER FETCH| | 8168 | 16336 | 19 (0)| 00:00:01 | | |
| 7 | FAST DUAL | | 1 | | 2 (0)| 00:00:01 | | |
| 8 | PARTITION RANGE MULTI-COLUMN | | 7 | | 73 (0)| 00:00:01 |KEY(MC)|KEY(MC)|
|* 9 | INDEX RANGE SCAN | TRANSACTION_LOG_2IX | 7 | | 73 (0)| 00:00:01 |KEY(MC)|KEY(MC)|
|* 10 | TABLE ACCESS BY LOCAL INDEX ROWID | TRANSACTION_LOG | 1 | 69 | 73 (0)| 00:00:01 | 1 | 1 |
----------------------------------------------------------------------------------------------------------------------------------
改進空間還是很有限的。
對此我的建議還是能夠從多個方面來考慮。
首先就是索引,目前存在3個索引,其實TRANSACTION_LOG_1IX和TRANSACTION_LOG_2IX都是非唯一性索引,如果能夠使用TRANSACTION_LOG_PK其實還是有很大的改進空間。和開發同事的交流來看,他們認為改動難度較大,需要改動的程式碼量很大,可能需要的時間也較長。但是也不失為一種方式。所以這個方案也是可行但是能不能落地還是一個問號。畢竟在雙方的一個權衡中也需要很多的協調。
第二個改進就是和開發的交流和自己抓取的一些資訊,發現transaction_id的取值範圍還是很大,這也是資料過濾較慢的一個原因。可以從執行計劃的謂詞資訊中看出來一些。首先是根據account_id來進行定位,但是資料過濾是根據transaction_id來做的。做這個時候
9 - access("TRANSACTION_LOG"."ACCOUNT_ID"=:1 AND "TRANSACTION_LOG"."TRANS_TYPE"="TRANSTYPE")
10 - filter(("TRANSACTION_LOG"."TRANSACTION_ID">=:3 AND "TRANSACTION_LOG"."TRANSACTION_ID"<=:4 AND
"TRANSACTION_LOG"."PARTITION_ID"=:2))
所以經過討論一種可行的效果就是能夠不盡可能的縮短transaction_id的範圍。使得transaction_id的範圍儘量小一些,資料過濾就會更加高效。這個從前端來說還是比較容易來實現的。
經過驗證發現速度還是比較理想的,調整了範圍之後,速度都在毫秒。
Elapsed: 00:00:00.70
來自 “ ITPUB部落格 ” ,連結:http://blog.itpub.net/23718752/viewspace-1701673/,如需轉載,請註明出處,否則將追究法律責任。
相關文章
- 一條update語句的優化探索優化
- 一條SQL語句的書寫SQL
- 一條很 巧妙的 SQL 語句SQL
- 一條sql語句的優化SQL優化
- 一條SQL語句的旅行之路SQL
- 一條簡單SQL語句的構成及語句解析SQL
- 一條sql語句的執行過程SQL
- 一條SQL語句的優化過程SQL優化
- 一條update SQL語句是如何執行的SQL
- 一條SQL更新語句是如何執行的SQL
- 一條SQL更新語句是如何執行的?SQL
- 一條全表掃描sql語句的分析SQL
- 一條sql語句的建議調優分析SQL
- 一條SQL的改寫SQL
- 一條更新的SQL語句是如何執行的?SQL
- 一條 SQL 查詢語句是如何執行的?SQL
- 一條SQL語句在MySQL中如何執行的MySql
- 實現四則運算的一條sql語句SQL
- PL/SQL 條件控制語句SQL
- SQL SERVER 條件語句的查詢SQLServer
- MyBatis 一次執行多條SQL語句MyBatisSQL
- 【SQL】使用一條INSERT語句完成多表插入SQL
- 一條sql語句在mysql中是如何執行的MySql
- 一條SQL語句的執行計劃變化探究SQL
- 一條 SQL 語句在 MySQL 中是如何執行的?MySql
- 常用sql進階語句SQL
- 一條sql語句優化不出來, 哭了一鼻子SQL優化
- MySQL日誌(一條sql更新語句是如何執行的)MySql
- 由一條sql語句導致的系統IO問題SQL
- Merge into: Oracle中用一條SQL語句直接進行Insert/Update的操作(R1)OracleSQL
- 一條簡單的sql語句導致的系統問題SQL
- 一條簡單的sql語句執行15天的原因分析SQL
- SQL語句優化--十條經驗SQL優化
- 執行一條sql語句都經歷了什麼?SQL
- 執行一條 SQL 語句,期間發生了什麼?SQL
- 使用sql語句查詢平均值,使用sql語句查詢資料總條數, not in 篩選語句的使用SQL
- 騰訊面試:一條SQL語句執行得很慢的原因有哪些?面試SQL
- MySQL系列之一條SQL查詢語句的執行過程MySql