久久精品人人爽,华人av在线,亚洲性视频网站,欧美专区一二三

SQL Server中怎么優(yōu)化多表查詢(xún)

共計(jì) 4262 個(gè)字符,預(yù)計(jì)需要花費(fèi) 11 分鐘才能閱讀完成。

這期內(nèi)容當(dāng)中丸趣 TV 小編將會(huì)給大家?guī)?lái)有關(guān) SQL Server 中怎么優(yōu)化多表查詢(xún),文章內(nèi)容豐富且以專(zhuān)業(yè)的角度為大家分析和敘述,閱讀完這篇文章希望大家可以有所收獲。

1. 執(zhí)行路徑

ORACLE 的這個(gè)功能大大地提高了 SQL 的執(zhí)行性能并節(jié)省了內(nèi)存的使用: 我們發(fā)現(xiàn), 單表數(shù)據(jù)的統(tǒng)計(jì)比多表統(tǒng)計(jì)的速度完全是兩個(gè)概念. 單表統(tǒng)計(jì)可能只要 0.02 秒, 但是 2 張表聯(lián)合統(tǒng)計(jì)就

可能要幾十秒了. 這是因?yàn)?ORACLE 只對(duì)簡(jiǎn)單的表提供高速緩沖(cache buffering) , 這個(gè)功能并不適用于多表連接查詢(xún).. 數(shù)據(jù)庫(kù)管理員必須在 init.ora 中為這個(gè)區(qū)域設(shè)置合適的參數(shù), 當(dāng)這個(gè)內(nèi)存區(qū)域越大, 就可以保留更多的語(yǔ)句, 當(dāng)然被共享的可能性也就越大了.

2. 選擇最有效率的表名順序(記錄少的放在后面)

ORACLE 的解析器按照從右到左的順序處理 FROM 子句中的表名, 因此 FROM 子句中寫(xiě)在最后的表 (基礎(chǔ)表 driving table) 將被最先處理. 在 FROM 子句中包含多個(gè)表的情況下, 你必須選擇記錄條數(shù)最少的表作為基礎(chǔ)表. 當(dāng) ORACLE 處理多個(gè)表時(shí), 會(huì)運(yùn)用排序及合并的方式連接它們. 首先, 掃描第一個(gè)表 (FROM 子句中最后的那個(gè)表) 并對(duì)記錄進(jìn)行派序, 然后掃描第二個(gè)表(FROM 子句中最后第二個(gè)表), 最后將所有從第二個(gè)表中檢索出的記錄與第一個(gè)表中合適記錄進(jìn)行合并.

例如:

表 TAB1 16,384 條記錄

表 TAB2 1 條記錄

選擇 TAB2 作為基礎(chǔ)表 (最好的方法)

select count(*) from tab1,tab2 執(zhí)行時(shí)間 0.96 秒

選擇 TAB2 作為基礎(chǔ)表 (不佳的方法)

select count(*) from tab2,tab1 執(zhí)行時(shí)間 26.09 秒

如果有 3 個(gè)以上的表連接查詢(xún), 那就需要選擇交叉表 (intersection table) 作為基礎(chǔ)表, 交叉表是指那個(gè)被其他表所引用的表.

例如: EMP 表描述了 LOCATION 表和 CATEGORY 表的交集.

SELECT * FROM LOCATION L , CATEGORY C, EMP E WHERE E.EMP_NO BETWEEN 1000 AND 2000 AND E.CAT_NO = C.CAT_NO AND E.LOCN = L.LOCN

將比下列 SQL 更有效率

SELECT * FROM EMP E , LOCATION L , CATEGORY C WHERE E.CAT_NO = C.CAT_NO AND E.LOCN = L.LOCN AND E.EMP_NO BETWEEN 1000 AND 2000

3.WHERE 子句中的連接順序(條件細(xì)的放在后面)

ORACLE 采用自下而上的順序解析 WHERE 子句, 根據(jù)這個(gè)原理, 表之間的連接必須寫(xiě)在其他 WHERE 條件之前, 那些可以過(guò)濾掉最大數(shù)量記錄的條件必須寫(xiě)在 WHERE 子句的末尾.

例如:

(低效, 執(zhí)行時(shí)間 156.3 秒)

SELECT … FROM EMP E WHERE SAL   50000 AND JOB = ‘MANAGER  AND 25   (SELECT COUNT(*) FROM EMP WHERE MGR=E.EMPNO); (高效, 執(zhí)行時(shí)間 10.6 秒) SELECT … FROM EMP E WHERE 25   (SELECT COUNT(*) FROM EMP WHERE MGR=E.EMPNO) AND SAL   50000 AND JOB = ‘MANAGER

4.SELECT 子句中避免使用 *

當(dāng)你想在 SELECT 子句中列出所有的 COLUMN 時(shí), 使用動(dòng)態(tài) SQL 列引用 * 是一個(gè)方便的方法. 不幸的是, 這是一個(gè)非常低效的方法. 實(shí)際上,ORACLE 在解析的過(guò)程中, 會(huì)將 * 依次轉(zhuǎn)換成所有的列名, 這個(gè)工作是通過(guò)查詢(xún)數(shù)據(jù)字典完成的, 這意味著將耗費(fèi)更多的時(shí)間.

5. 減少訪(fǎng)問(wèn)數(shù)據(jù)庫(kù)的次數(shù)

當(dāng)執(zhí)行每條 SQL 語(yǔ)句時(shí), ORACLE 在內(nèi)部執(zhí)行了許多工作: 解析 SQL 語(yǔ)句, 估算索引的利用率, 綁定變量 , 讀數(shù)據(jù)塊等等. 由此可見(jiàn), 減少訪(fǎng)問(wèn)數(shù)據(jù)庫(kù)的次數(shù) , 就能實(shí)際上減少 ORACLE 的工作量.

方法 1 (低效)

SELECT EMP_NAME , SALARY , GRADE FROM EMP WHERE EMP_NO = 342; SELECT EMP_NAME , SALARY , GRADE FROM EMP WHERE EMP_NO = 291;

方法 2 (高效)

SELECT A.EMP_NAME , A.SALARY , A.GRADE, B.EMP_NAME , B.SALARY , B.GRADE FROM EMP A,EMP B WHERE A.EMP_NO = 342 AND B.EMP_NO = 291;

6. 刪除重復(fù)記錄

最高效的刪除重復(fù)記錄方法 (因?yàn)槭褂昧?ROWID)

DELETE FROM EMP E WHERE E.ROWID   (SELECT MIN(X.ROWID) FROM EMP X WHERE X.EMP_NO = E.EMP_NO);

7. 用 TRUNCATE 替代 DELETE

當(dāng)刪除表中的記錄時(shí), 在通常情況下, 回滾段(rollback segments) 用來(lái)存放可以被恢復(fù)的信息. 如果你沒(méi)有 COMMIT 事務(wù),ORACLE 會(huì)將數(shù)據(jù)恢復(fù)到刪除之前的狀態(tài)(準(zhǔn)確地說(shuō)是恢復(fù)到執(zhí)行刪除命令之前的狀況),而當(dāng)運(yùn)用 TRUNCATE 時(shí), 回滾段不再存放任何可被恢復(fù)的信息. 當(dāng)命令運(yùn)行后, 數(shù)據(jù)不能被恢復(fù). 因此很少的資源被調(diào)用, 執(zhí)行時(shí)間也會(huì)很短.

8. 盡量多使用 COMMIT

只要有可能, 在程序中盡量多使用 COMMIT, 這樣程序的性能得到提高, 需求也會(huì)因?yàn)?COMMIT 所釋放的資源而減少:

COMMIT 所釋放的資源:

a. 回滾段上用于恢復(fù)數(shù)據(jù)的信息.

b. 被程序語(yǔ)句獲得的鎖

c. redo log buffer 中的空間

d. ORACLE 為管理上述 3 種資源中的內(nèi)部花費(fèi)(在使用 COMMIT 時(shí)必須要注意到事務(wù)的完整性, 現(xiàn)實(shí)中效率和事務(wù)完整性往往是魚(yú)和熊掌不可得兼)

9. 減少對(duì)表的查詢(xún)

在含有子查詢(xún)的 SQL 語(yǔ)句中, 要特別注意減少對(duì)表的查詢(xún).

例如:

低效:

SELECT TAB_NAME FROM TABLES WHERE TAB_NAME = ( SELECT TAB_NAME FROM TAB_COLUMNS WHERE VERSION = 604) AND DB_VER= ( SELECT DB_VER FROM TAB_COLUMNS WHERE VERSION = 604

高效:

SELECT TAB_NAME FROM TABLES WHERE (TAB_NAME,DB_VER) = ( SELECT TAB_NAME,DB_VER) FROM TAB_COLUMNS WHERE VERSION = 604)

Update 多個(gè) Column 例子:

低效:

UPDATE EMP SET EMP_CAT = (SELECT MAX(CATEGORY) FROM EMP_CATEGORIES), SAL_RANGE = (SELECT MAX(SAL_RANGE) FROM EMP_CATEGORIES) WHERE EMP_DEPT = 0020;

高效:

UPDATE EMP SET (EMP_CAT, SAL_RANGE) = (SELECT MAX(CATEGORY) , MAX(SAL_RANGE) FROM EMP_CATEGORIES) WHERE EMP_DEPT = 0020;

10. 用 EXISTS 替代 IN, 用 NOT EXISTS 替代 NOT IN

在許多基于基礎(chǔ)表的查詢(xún)中, 為了滿(mǎn)足一個(gè)條件, 往往需要對(duì)另一個(gè)表進(jìn)行聯(lián)接. 在這種情況下, 使用 EXISTS(或 NOT EXISTS)通常將提高查詢(xún)的效率.

低效:

SELECT * FROM EMP (基礎(chǔ)表) WHERE EMPNO   0 AND DEPTNO IN (SELECT DEPTNO FROM DEPT WHERE LOC = ‘MELB)

高效:

SELECT * FROM EMP (基礎(chǔ)表) WHERE EMPNO   0 AND EXISTS (SELECT ‘X  FROM DEPT WHERE DEPT.DEPTNO = EMP.DEPTNO AND LOC = ‘MELB)

(相對(duì)來(lái)說(shuō), 用 NOT EXISTS 替換 NOT IN 將更顯著地提高效率)

在子查詢(xún)中,NOT IN 子句將執(zhí)行一個(gè)內(nèi)部的排序和合并. 無(wú)論在哪種情況下,NOT IN 都是最低效的 (因?yàn)樗鼘?duì)子查詢(xún)中的表執(zhí)行了一個(gè)全表遍歷). 為了避免使用 NOT IN , 我們可以把它改寫(xiě)成外連接 (Outer Joins) 或 NOT EXISTS.

例如:

SELECT … FROM EMP WHERE DEPT_NO NOT IN (SELECT DEPT_NO FROM DEPT WHERE DEPT_CAT= A

為了提高效率. 改寫(xiě)為:

(方法一: 高效)

SELECT …. FROM EMP A,DEPT B WHERE A.DEPT_NO = B.DEPT(+) AND B.DEPT_NO IS NULL AND B.DEPT_CAT(+) =  A

(方法二: 最高效)

SELECT …. FROM EMP E WHERE NOT EXISTS (SELECT  X  FROM DEPT D WHERE D.DEPT_NO = E.DEPT_NO AND DEPT_CAT =  A

當(dāng)然, 最高效率的方法是有表關(guān)聯(lián). 直接兩表關(guān)系對(duì)聯(lián)的速度是最快的!

11. 識(shí)別 低效執(zhí)行 的 SQL 語(yǔ)句

用下列 SQL 工具找出低效 SQL:

SELECT EXECUTIONS , DISK_READS, BUFFER_GETS, ROUND((BUFFER_GETS-DISK_READS)/BUFFER_GETS,2) Hit_radio, ROUND(DISK_READS/EXECUTIONS,2) Reads_per_run, SQL_TEXT FROM V$SQLAREA WHERE EXECUTIONS 0 AND BUFFER_GETS   0 AND (BUFFER_GETS-DISK_READS)/BUFFER_GETS   0.8 ORDER BY 4 DESC;

上述就是丸趣 TV 小編為大家分享的 SQL Server 中怎么優(yōu)化多表查詢(xún)了,如果剛好有類(lèi)似的疑惑,不妨參照上述分析進(jìn)行理解。如果想知道更多相關(guān)知識(shí),歡迎關(guān)注丸趣 TV 行業(yè)資訊頻道。

正文完
 
丸趣
版權(quán)聲明:本站原創(chuàng)文章,由 丸趣 2023-08-03發(fā)表,共計(jì)4262字。
轉(zhuǎn)載說(shuō)明:除特殊說(shuō)明外本站除技術(shù)相關(guān)以外文章皆由網(wǎng)絡(luò)搜集發(fā)布,轉(zhuǎn)載請(qǐng)注明出處。
評(píng)論(沒(méi)有評(píng)論)
主站蜘蛛池模板: 伊春市| 大宁县| 济宁市| 鹰潭市| 红桥区| 海口市| 永州市| 承德市| 六安市| 绍兴县| 景宁| 达州市| 胶南市| 疏勒县| 商城县| 贺兰县| 舞阳县| 象州县| 旬阳县| 启东市| 卢氏县| 恩施市| 隆昌县| 遵义县| 孟村| 正宁县| 定边县| 秦安县| 达尔| 区。| 剑川县| 长顺县| 读书| 图木舒克市| 辽源市| 绥阳县| 云霄县| 耿马| 漳浦县| 古交市| 边坝县|