明輝手游網(wǎng)中心:是一個(gè)免費(fèi)提供流行視頻軟件教程、在線(xiàn)學(xué)習(xí)分享的學(xué)習(xí)平臺(tái)!

6個(gè)容易的SQL優(yōu)化 SELECT 語(yǔ)句

[摘要]SELECT語(yǔ)句的性能調(diào)優(yōu)有時(shí)是一個(gè)非常耗時(shí)的任務(wù),在我看來(lái)它遵循帕累托原則。20%的努力很可能會(huì)給你帶來(lái)80%的性能提升,而為了獲得另外20%的性能提升你可能需要花費(fèi)80%的時(shí)間。除非你在金星工作,那里的每一天都等于地球上的243天,否則交付期限很有可能使你沒(méi)有足夠的時(shí)間來(lái)調(diào)優(yōu)SQL查詢(xún)。根據(jù)我...

SELECT語(yǔ)句的性能調(diào)優(yōu)有時(shí)是一個(gè)非常耗時(shí)的任務(wù),在我看來(lái)它遵循帕累托原則。20%的努力很可能會(huì)給你帶來(lái)80%的性能提升,而為了獲得另外20%的性能提升你可能需要花費(fèi)80%的時(shí)間。除非你在金星工作,那里的每一天都等于地球上的243天,否則交付期限很有可能使你沒(méi)有足夠的時(shí)間來(lái)調(diào)優(yōu)SQL查詢(xún)。

根據(jù)我多年編寫(xiě)和運(yùn)行SQL語(yǔ)句的經(jīng)驗(yàn),我開(kāi)始開(kāi)發(fā)一個(gè)檢查列表,當(dāng)我試圖提高查詢(xún)性能時(shí)供我參考。在進(jìn)行查詢(xún)計(jì)劃和閱讀我使用的數(shù)據(jù)庫(kù)文檔之前,我會(huì)參考其中的內(nèi)容,數(shù)據(jù)庫(kù)文檔有時(shí)會(huì)很復(fù)雜。我的檢查列表絕對(duì)說(shuō)不上全面或科學(xué),它更像是一個(gè)保守計(jì)算,但我可以說(shuō),遵循這些簡(jiǎn)單的步驟大部分時(shí)間我確實(shí)能得到性能提升。檢查列表如下。

檢查索引

在SQL語(yǔ)句的WHERE和JOIN部分中用到的所有字段上,都應(yīng)該加上索引。進(jìn)行這個(gè)3分鐘SQL性能測(cè)試。不管你的成績(jī)?nèi)绾,一定要閱讀那些帶有信息的結(jié)果。

限制工作數(shù)據(jù)集的大小

檢查那些SELECT語(yǔ)句中用到的表,看看你是否可以應(yīng)用WHERE子句進(jìn)行過(guò)濾。一個(gè)典型的例子是,當(dāng)表中只有幾千行記錄時(shí),一個(gè)查詢(xún)能夠很好地執(zhí)行。但隨著應(yīng)用程序的成長(zhǎng),查詢(xún)慢了下來(lái)。解決方案或許非常簡(jiǎn)單,限制查詢(xún)來(lái)查看當(dāng)前月的數(shù)據(jù)即可。

當(dāng)你的查詢(xún)語(yǔ)句帶有子查詢(xún)時(shí),注意在子查詢(xún)的內(nèi)部語(yǔ)句上使用過(guò)濾,而不是在外部語(yǔ)句上。

只選擇你需要的字段

額外的字段通常會(huì)增加返回?cái)?shù)據(jù)的紋理,從而導(dǎo)致更多的數(shù)據(jù)被返回到SQL客戶(hù)端。另外:

?使用帶有報(bào)告和分析功能的應(yīng)用程序時(shí),有時(shí)報(bào)告性能低是因?yàn)閳?bào)告工具必須對(duì)收到的、帶有詳細(xì)形式的數(shù)據(jù)做聚合操作。

?偶爾查詢(xún)也可能運(yùn)行地足夠快,但你的問(wèn)題可能是一個(gè)網(wǎng)絡(luò)相關(guān)的問(wèn)題,因?yàn)榇罅康脑敿?xì)數(shù)據(jù)通過(guò)網(wǎng)絡(luò)發(fā)送到報(bào)告服務(wù)器。

?當(dāng)使用一個(gè)面向列的DBMS時(shí),只有你選擇的列會(huì)從磁盤(pán)讀取。在你的查詢(xún)中包含的列越少,IO開(kāi)銷(xiāo)就越小。

移除不必要的表

移除不必要的表的原因,和移除查詢(xún)語(yǔ)句中不需要的字段的原因一致。

編寫(xiě)SQL語(yǔ)句是一個(gè)過(guò)程,通常需要大量編寫(xiě)和測(cè)試SQL語(yǔ)句的迭代過(guò)程。在開(kāi)發(fā)過(guò)程中,你可能將表添加到查詢(xún)中,而這對(duì)于SQL代碼返回的數(shù)據(jù)可能不會(huì)有任何影響。一旦SQL運(yùn)行正確,我發(fā)現(xiàn)許多人不會(huì)回顧他們的腳本,不會(huì)刪除那些對(duì)最終的返回?cái)?shù)據(jù)沒(méi)有任何影響和作用的表。通過(guò)移除與那些不必要表的JOINS操作,你減少了大量數(shù)據(jù)庫(kù)必須執(zhí)行的流程。有時(shí),就像移除列一樣,你會(huì)發(fā)現(xiàn)你減少的數(shù)據(jù)又通過(guò)數(shù)據(jù)庫(kù)返回來(lái)了。

移除外部連接查詢(xún)

這說(shuō)起來(lái)容易做起來(lái)難,它取決于改變表的內(nèi)容有多大的影響。一個(gè)解決辦法是通過(guò)在兩個(gè)表的行中放置占位符來(lái)刪除OUTER JOINS操作。假設(shè)你有以下的表,它們通過(guò)定義OUTER JOINS來(lái)確保返回所有的數(shù)據(jù):

CUSTOMER_IDCUSTOMER_NAME
1John Doe
2Mary Jane
3Peter Pan
4Joe Soap
CUSTOMER_IDSALES_PERSON
NULLNewbee Smith
2Oldie Jones
1Another Oldie
NULLGreenhorn

解決辦法是在customer表的行中增加一個(gè)占位符,并更新sales表中的所有NULL值到占位符。

CUSTOMER_IDCUSTOMER_NAME
0NO CUSTOMER
1John Doe
2Mary Jane
3Peter Pan
4Joe Soap
CUSTOMER_IDSALES_PERSON
0Newbee Smith
2Oldie Jones
1Another Oldie
0Greenhorn

你不只是刪除了對(duì)OUTER JOIN操作的依賴(lài),同時(shí)標(biāo)準(zhǔn)化了沒(méi)有客戶(hù)的銷(xiāo)售人員如何表示。其他開(kāi)發(fā)人員不必編寫(xiě)額外語(yǔ)句,例如ISNULL(customer_id, “No customer yet”)。

刪除JOIN和WHERE子句中的計(jì)算字段

這是另外一個(gè)有時(shí)可能說(shuō)起來(lái)容易做起來(lái)難的技巧,它取決于你更改表模式的權(quán)限大小?梢詫⑦B接語(yǔ)句中用到的計(jì)算字段作為一個(gè)新字段在表中創(chuàng)建。給出以下SQL語(yǔ)句:

FROM sales a 
JOIN budget b ON    ((YEAR(a.sale_date)* 100) + MONTH(a.sale_date)) = b.budget_year_month

在sales表中利用年和月增加一列,可以提高性能。更新后的SQL語(yǔ)句將如下:

SELECT * FROM PRODUCTSFROM sales a 
JOIN budget b ON    a.sale_year_month = b.budget_year_month

總結(jié)

上邊的建議可以歸結(jié)為以下幾點(diǎn):

?檢查索引

?在所需要的最小數(shù)據(jù)集上操作

?移除不必要的字段和表

?移除你JOIN和WHERE子句中的計(jì)算操作

如果所有的這些建議都沒(méi)能提高你的SQL查詢(xún)性能,最后一個(gè)建議是搬去金星吧。你需要的就是一天能調(diào)優(yōu)你的SQL語(yǔ)句。

以上就是6個(gè)簡(jiǎn)單的SQL優(yōu)化 SELECT 語(yǔ)句的詳細(xì)內(nèi)容,更多請(qǐng)關(guān)注php中文網(wǎng)其它相關(guān)文章!


學(xué)習(xí)教程快速掌握從入門(mén)到精通的SQL知識(shí)。