天天看點

【書評:Oracle查詢優化改寫】第一章

【書評:Oracle查詢優化改寫】第一章

BLOG文檔結構圖:

【書評:Oracle查詢優化改寫】第一章

之前幫助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; 的結果是多少?

【書評:Oracle查詢優化改寫】第一章

答案:5.2   空值是不參與運算的

【書評:Oracle查詢優化改寫】第一章

不知道書的後邊會不會講解如何讓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的文章标題