【書評:Oracle查詢優化改寫】第一章
BLOG文檔結構圖:
之前幫助ITPUB上的一位部落客修改過一個很明顯的錯誤,ITPUB為了表達感謝特贈予一本技術方面的書籍,我可以自己選擇書名,想了想,自己對SQL優化特感興趣于是就訂了一本SQL優化改寫方面的書籍,書名為《Oracle查詢優化改寫》,其實這本書的作者我是認識的,之前數次在公開課上聽過他講過SQL優化改寫方面的内容,印象很深刻,好了,不多說了,說多了有打廣告的嫌疑。
最近一直在學習rac方面的内容,但是rac高可用性,這個方面很難寫,寫淺了感覺浪費時間,也浪費讀者的時間,寫深了又怕出錯,誤導别人,在自己未完全了解的情況下,不想随便釋出blog,但總得釋出一點啥吧,想了想不如就寫寫讀後感吧,基于自己本身喜歡SQL優化方面的内容,又有書在手,那就寫寫書中的内容吧,有好的例子,我試驗下給大家分享出來,今天我們就看看這本書的第一章的内容吧。
第一章很簡單,就講了下單表查詢的内容,目錄參考後邊附錄部分,大緻包含:NULL上常犯的錯誤、字元串中單引号的處理方式及模糊查詢時對通配符的轉義。
第 1 章 單表查詢
1.1 查詢表中所有的行與列
1.2 從表中檢索部分行
1.3 查找空值
1.4 将空值轉換為實際值
1.5 查找滿足多個條件的行
1.6 從表中檢索部分列
1.7 為列取有意義的名稱
1.8 在 WHERE 子句中引用取别名的列
1.9 拼接列
1.10 在 SELECT 語句中使用條件邏輯
1.11 限制傳回的行數
1.12 從表中随機傳回 n 條記錄
1.13 模糊查詢
這個很簡單,但是容易出錯,可以認為是重點,判斷為空或者不為空的時候,隻能采用is null 或者is not null,不能用=null,任何空值做加減乘除大小比較或相等比較結果都為空,這個沒啥實驗的,oracle入門必學的一些内容,另外還有一些處理空值的函數,例如nvl、coalesce等,這部分就不做實驗了,書中沒有如下的内容,我補充一些,也是書是講SQL優化改寫的,又不是講解文法的。
解釋:
1. 空值是無效的,未指定的,未知的或不可預知的值。
2. 空值不是空格也不是0。
3. 包含空值的數學表達式的值(即加減乘除等操作)都為空值null
4. 對空值進行連接配接字元串的操作之後,傳回為被連接配接的字元串。
5. 為空用is null 來表示,不為空用 is not null 來表示,除此之外沒有其它的表示方法了,這一點尤為重要!!!!!!
6. 除了count(1) 和count(*) 外的其它函數都不計算空值
7. Null 在排序中預設為最大值,desc在最前,asc在最後,可以加上nulls last 來限制null值的顯示
辦法:使用 nvl 函數來處理
SELECT sal*13+nvl(comm, 0)*13 "年薪" , ename, comm FROM emp;
問題:如何顯示沒有上級的雇員的情況?
錯誤寫法:select * from emp where mgr = '';
正确寫法:SELECT * FROM emp WHERE mgr is null;
1. 有如下的資料,請問select avg(age) from stuInfo; 的結果是多少?
答案:5.2 空值是不參與運算的
不知道書的後邊會不會講解如何讓is null走索引的内容,我這裡先給大家講講如何讓is null去走索引吧。
解決辦法: is null 加僞列建立僞聯合索引來使得is null使用索引
[oracle@node2 ~]$ sqlplus / as sysdba
SQL*Plus: Release 11.2.0.1.0 Production on Wed May 13 17:29:16 2015
Copyright (c) 1982, 2009, Oracle. All rights reserved.
Connected to:
Oracle Database 11g Enterprise Edition Release 11.2.0.1.0 - 64bit Production
With the Partitioning, Real Application Clusters, Automatic Storage Management, OLAP,
Data Mining and Real Application Testing options
SQL> create table lhr.t2 as select * from dba_objects;
Table created.
SQL> select * from lhr.t2 where object_id is null;
no rows selected
SQL> set autot on;
Execution Plan
----------------------------------------------------------
Plan hash value: 1513984157
--------------------------------------------------------------------------
| Id | Operation | Name | Rows | Bytes | Cost (%CPU)| Time |
| 0 | SELECT STATEMENT | | 12 | 2484 | 289 (1)| 00:00:04 |
|* 1 | TABLE ACCESS FULL| T2 | 12 | 2484 | 289 (1)| 00:00:04 |
Predicate Information (identified by operation id):
---------------------------------------------------
1 - filter("OBJECT_ID" IS NULL)
Note
-----
- dynamic sampling used for this statement (level=2)
Statistics
0 recursive calls
0 db block gets
1035 consistent gets
1032 physical reads
0 redo size
1343 bytes sent via SQL*Net to client
512 bytes received via SQL*Net from client
1 SQL*Net roundtrips to/from client
0 sorts (memory)
0 sorts (disk)
0 rows processed
SQL> create index ind_t2_id on lhr.t2(object_id);
Index created.
SQL> exec dbms_stats.gather_index_stats('SYS','ind_t2_id');
PL/SQL procedure successfully completed.
935 recursive calls
1238 consistent gets
1102 physical reads
6 sorts (memory)
SQL> DROP INDEX ind_t2_id;
Index dropped.
SQL> create index LHR.ind_t2_id on lhr.t2(object_id,-1);
SQL> exec dbms_stats.gather_index_stats('LHR','ind_t2_id');
SQL> SET LINE 9999
Plan hash value: 2868503181
-----------------------------------------------------------------------------------------
| Id | Operation | Name | Rows | Bytes | Cost (%CPU)| Time |
| 0 | SELECT STATEMENT | | 12 | 2484 | 67 (0)| 00:00:01 |
| 1 | TABLE ACCESS BY INDEX ROWID| T2 | 12 | 2484 | 67 (0)| 00:00:01 |
|* 2 | INDEX RANGE SCAN | IND_T2_ID | 4071 | | 12 (0)| 00:00:01 |
2 - access("OBJECT_ID" IS NULL)
2 consistent gets
0 physical reads
SQL>
可以看出過濾條件中is null走了索引。
以我的sql優化經驗而言,強烈建議表加别名,尤其對于sql中是多張表關聯的時候更應對每一個表加上别名。
3 從表中随機傳回N條記錄
正确寫法:select empno,ename from ( select empno,ename from scott.emp order by dbms_random.value()) where rownum
錯誤寫法:select empno,ename from scott.emp where rownum
SQL> select empno,ename from ( select empno,ename from scott.emp order by dbms_random.value()) where rownum
EMPNO ENAME
---------- ----------
7788 SCOTT
7934 MILLER
7900 JAMES
7782 CLARK
7369 SMITH
7499 ALLEN
SQL> select empno,ename from scott.emp where rownum
7521 WARD
簡單點的模糊查詢就不說了,但是在字元串中含有’\’的時候,雙寫\\即可。
SQL> create or replace view v as select '_\BCEDF' VNAME FROM DUAL;
View created.
SQL> SELECT * FROM V WHERE VNAME LIKE '_\BC%' ESCAPE '\';
SELECT * FROM V WHERE VNAME LIKE '_\BC' ESCAPE '\'
*
ERROR at line 1:
ORA-01424: missing or illegal character following the escape character
SQL> SELECT * FROM V WHERE VNAME LIKE '_\\BC%' ESCAPE '\';
VNAME
-------
_\BCEDF
好了,第一章内容基本上就這些,後邊等我閱讀了第二章後再給大家分享吧。
...........................................................................................................................................................................................
本文作者:小麥苗,隻專注于資料庫的技術,更注重技術的運用
QQ:642808185 注明:ITPUB的文章标題