[20220109]開發不應該這樣寫SQL語句.txt
[20220109]開發不應該這樣寫SQL語句.txt
--//最近一段時間最佳化sql語句,遇到一個語句我開始以為我能夠最佳化它,結果仔細檢查嘗試後發現不行,在測試環境做一個例子演示出來看
--//看.
1.環境:
SCOTT@book> @ ver1
PORT_STRING VERSION BANNER
------------------------------ -------------- --------------------------------------------------------------------------------
x86_64/Linux 2.4.xx 11.2.0.4.0 Oracle Database 11g Enterprise Edition Release 11.2.0.4.0 - 64bit Production
2.測試建立:
create table tx as select * from all_objects ;
create index i_tx_object_id on tx(object_id);
create index i_tx_data_object_id on tx(data_object_id);
SCOTT@book> update tx set data_object_id=-1 where data_object_id=0;
4 rows updated.
SCOTT@book> commit ;
Commit complete.
--//取消data_object_id=0的情況。
--//分析表.
SCOTT@book> @ gts tx
Gather Table Statistics for table tx...
PL/SQL procedure successfully completed.
3.語句:
SELECT object_id,data_object_id,object_name
FROM tx
WHERE (object_id = :a or :a = 0)
AND (data_object_id = :b or :b = 0);
--//正常情況帶入的引數是一個為0,另外1個不為0.透過這樣的方式實現雙查.
--//一開始看到語句我以為我可以最佳化該語句,實際上我做了許多嘗試,最終放棄.
--//這種寫法不知道算不算開發程式設計sql語句的一種技巧,實際上開發應該寫成如下,邏輯即簡單又明瞭.
SELECT object_id,data_object_id,object_name
FROM tx
WHERE ( object_id = :a or data_object_id = :b );
--//開發還喜歡寫成如下:
SELECT object_name
FROM tx
WHERE ( :v_choice = 1 AND object_id = :a)
OR ( :v_choice = 2 AND data_object_id = :b );
4.當然如果不使用繫結變數,以下可以正常使用索引.
SELECT object_id,data_object_id,object_name
FROM tx
WHERE (object_id = 0 or 0 = 0)
AND (data_object_id = 10 or 10 = 0);
SELECT object_id,data_object_id,object_name
SELECT object_name
FROM tx
WHERE (object_id = 10 or 10 = 0)
AND (data_object_id = 0 or 0 = 0);
--//我看了以前的最佳化筆記,使用提示寫成如下:
/* Formatted on 2022/01/10 9:49:13 (QP5 v5.269.14213.34769) */
SELECT /*+ USE_CONCAT(@"SEL$1" 8 OR_PREDICATES(1) PREDICATE_REORDERS((2 3) (3 2))) */
object_id, data_object_id, object_name
FROM tx
WHERE (object_id = :a OR :a = 0) AND (data_object_id = :b OR :b = 0);
Plan hash value: 3150342875
-----------------------------------------------------------------------------------------------------------------------------------------
| Id | Operation | Name | Starts | E-Rows |E-Bytes| Cost (%CPU)| E-Time | A-Rows | A-Time | Buffers |
-----------------------------------------------------------------------------------------------------------------------------------------
| 0 | SELECT STATEMENT | | 1 | | | 340 (100)| | 1 |00:00:00.02 | 1218 |
| 1 | CONCATENATION | | 1 | | | | | 1 |00:00:00.02 | 1218 |
|* 2 | TABLE ACCESS BY INDEX ROWID| TX | 1 | 1 | 32 | 2 (0)| 00:00:01 | 0 |00:00:00.01 | 2 |
|* 3 | INDEX RANGE SCAN | I_TX_OBJECT_ID | 1 | 1 | | 1 (0)| 00:00:01 | 0 |00:00:00.01 | 2 |
|* 4 | FILTER | | 1 | | | | | 1 |00:00:00.02 | 1216 |
|* 5 | TABLE ACCESS FULL | TX | 1 | 849 | 27168 | 338 (1)| 00:00:05 | 1 |00:00:00.02 | 1216 |
-----------------------------------------------------------------------------------------------------------------------------------------
Predicate Information (identified by operation id):
---------------------------------------------------
2 - filter(("DATA_OBJECT_ID"=:B OR :B=0))
3 - access("OBJECT_ID"=:A)
4 - filter(:A=0)
5 - filter((("DATA_OBJECT_ID"=:B OR :B=0) AND LNNVL("OBJECT_ID"=:A)))
Plan hash value: 3150342875
-----------------------------------------------------------------------------------------------------------------------------------------
| Id | Operation | Name | Starts | E-Rows |E-Bytes| Cost (%CPU)| E-Time | A-Rows | A-Time | Buffers |
-----------------------------------------------------------------------------------------------------------------------------------------
| 0 | SELECT STATEMENT | | 1 | | | 340 (100)| | 1 |00:00:00.01 | 3 |
| 1 | CONCATENATION | | 1 | | | | | 1 |00:00:00.01 | 3 |
|* 2 | TABLE ACCESS BY INDEX ROWID| TX | 1 | 1 | 32 | 2 (0)| 00:00:01 | 1 |00:00:00.01 | 3 |
|* 3 | INDEX RANGE SCAN | I_TX_OBJECT_ID | 1 | 1 | | 1 (0)| 00:00:01 | 1 |00:00:00.01 | 2 |
|* 4 | FILTER | | 1 | | | | | 0 |00:00:00.01 | 0 |
|* 5 | TABLE ACCESS FULL | TX | 0 | 849 | 27168 | 338 (1)| 00:00:05 | 0 |00:00:00.01 | 0 |
-----------------------------------------------------------------------------------------------------------------------------------------
--//但是會出現兩種情況,一種情況還是全表掃描。比如帶入 a:=0,b:=10的情況。要出現兩個索引都使用的情況才行。
--//不知道有什麼好的方法解決該問題。
來自 “ ITPUB部落格 ” ,連結:http://blog.itpub.net/267265/viewspace-2851445/,如需轉載,請註明出處,否則將追究法律責任。
相關文章
- [20220121]開發不應該這樣寫sql2.txtSQL
- [20220124]開發不應該這樣寫sql3.txtSQL
- [20231207]開發不應該這樣寫sql4.txtSQL
- [20220329]是否開發寫錯sql語句.txtSQL
- 如何寫這個sql語句?SQL
- 寫這段程式碼的人該不該被開除?
- markdown裡的微積分中dt應該這樣寫
- 6. Oracle開發和應用—6.3. 基本SQL語句—6.3.4. select語句OracleSQL
- sql語句抄寫作業SQL
- [20150403]修正sql語句.txtSQL
- 這樣的sql怎麼寫?SQL
- SQL語句規範的寫法SQL
- OCI插入SQL語句的寫法SQL
- 一條SQL語句的書寫SQL
- 不當編寫SQL語句導致系統不安全(轉)SQL
- 不當編寫SQL語句導致系統不安全 (轉)SQL
- SQL Story(十)————遊標的應該與不應該 (轉)SQL
- [20170103]sql語句過載.txtSQL
- 6. Oracle開發和應用—6.4. PL/SQL語法—6.4.4. 條件語句(分支語句)OracleSQL
- 面試?或許你應該這樣面試
- 【sql】編寫基本的SQL SELECT語句四SQL
- 【sql】編寫基本的SQL SELECT語句三SQL
- 【sql】編寫基本的SQL SELECT語句一SQL
- SQL語句大全,你需要的SQL在這裡SQL
- 作為一個IT技術開發,應該樹立這樣一個信念!
- 6. Oracle開發和應用—6.4. PL/SQL語法—6.4.1. 語句塊OracleSQL
- SQL語句寫到累了?試試GreenDAOSQL
- MySQL中常用SQL語句的編寫MySql
- 如何寫出高效能SQL語句SQL
- 【MySQL】經典資料庫SQL語句編寫練習題——SQL語句掃盲MySql資料庫
- SQL語句為什麼不會共享(上)SQL
- SQL語句為什麼不會共享(中)SQL
- SQL語句為什麼不會共享(下)SQL
- Clipped.js | Webpack 應該這樣用JSWeb
- MVP設計模式應該這樣掌握MVP設計模式
- mac 鍵盤應該這樣改鍵Mac
- 一份優秀的資料分析報告應該這樣寫
- 查詢正在執行的sql語句及該語句執行的時間SQL