Java教程之SQL性能優化提升
Ø 簡單的性能優化
Sql的性能優化是數據庫工程師在實際工作中必須面對的重要課題之一。對於某些數據庫工程師來說,它幾乎唯一的命題。實際上,像WEB服務這樣需要快速響應的應用場景中,SQL的性能直接決定了系統是否可以使用。這裏主要介紹一些使用SQL執行速度更快,消耗內存更少的優化技巧,今天的文章只介紹其中的一種,後續會繼續更新一些其它的優化方式。
嚴格地優化查詢性能時,必須要了解所使用的數據庫的功能特點。此外,查詢速度慢並不只是因為SQL語句本身,還可能是因為內存分配不佳,文件結構不合理等其他原因。因此這裏介紹的優化SQL的方法未必能解決所有的性能問題,但是確實很多時候的查詢性能不好的原因還是SQL的寫法不合理。
Ø 使用高效的查詢
在SQL中,很多時候不同代碼能夠得到相同的結果。從理論上來說,得到相同結果的不同代碼應該有相同的性能,但遺憾的是,查詢優化器生成的執行計劃很大程度要受到代碼外部結構的影響。因此如果想優化查詢性能,必須知道如何寫代碼才能使優化器的執行效率更高。
參數是子查詢時,使用EXISTS代替IN
IN謂詞非常方便,而且代碼容易理解,所以使用的頻率很高。但是方便的同時,IN謂詞卻有成為性能優化的瓶頸的危險。如果代碼中大量用到IN謂詞,那麽一般只對它們進行優化就能大幅度地提升性能。
如果IN的參數是“1,2,3”這樣的數值列表,一般還不需要特別註意。但是如果參數是子查詢,那麽就需要註意了。
大多數情況,[NOT]IN和[NOT]EXISTS返回的結果是相同的。但是兩者用於子查詢時,EXISTS的速度會更快一些。
下面來看個例子:
我們試著從Class_A表中查出同時存在於Class_B表中的員工。下面兩條SQL語句返回的結果是一樣的,但是使用EXISTS的SQL語句更快一些。
兩個結果都如下所示:
使用EXISTS時更快的原因有以下兩個。
a) 如果連接列(id)上建立了索引,那麽查詢Class_B時不用查詢實際的表,只需查索引就可以了。
b) 如果使用EXISTS,那麽只要查到一行數據滿足條件就會終止查詢,不用像使用IN時一樣掃描全表。在這一點上NOT EXISTS也一樣。
當IN的參數是子查詢時,數據庫首先會執行子查詢,然後將結果存儲在一張臨時的工作表裏(內聯視圖),然後掃描整個視圖。很多情況下這種做法都非常耗費資源。使用EXISTS的話,數據庫不會生成臨時的工作表。
但是從代碼的可讀性上來看,IN要比EXISTS好。使用IN時的代碼看起來更一目了然,易於理解。因此,如果確信使用IN也能快速獲取結果,就沒有必要非得改成EXISTS了。
而且,最近有很多數據庫也嘗試著改善了IN的性能。也許未來的某一天,無論哪個數據庫上,IN都能具體和EXISTS一樣的性能。
參數是子查詢時,使用連接代替IN
要想改善IN的性能,除了使用EXISTS,還可以使用連接。前面的查詢語句就可以像下面這樣“扁平化”。
這種寫法至少能用到一張表的“id”列上的索引。而且,因為沒有了子查詢,所以數據庫也不會生成中間表。我們很難說與EXISTS相比哪個更好,但是如果沒有索引,那麽與連接相比,可能EXISTS會略勝一籌。而且從很多查詢可以看出,有些情況下使用EXISTS比使用連接更合適。
Java教程之SQL性能優化提升