2010-10-05 25 views
3

爲了序言,我知道(應該如此!)在生產中使用SELECT *是不好的,但我維護着其他人編寫的腳本。而且,我也意識到這個問題在具體情況上很低......但是假設的情況。假設的性能良率不使用SELECT *

比方說,我有一個腳本,從20個字段的表中選擇一切。讓我們說典型的客戶信息。

然後讓我們說,作爲一名優秀的開發人員,我將SELECT *縮短爲實際使用的13個特定字段中的SELECT

通過明確列出字段與SELECT *相比,我可以期待什麼類型的性能優勢(如果有的話)?

我會這麼說,這兩個查詢都利用了相同的確切索引。如果您想知道,更具體的查詢無法訪問其他查詢無法使用的覆蓋索引。

我不期待奇蹟,就像添加一個針對更具體查詢的索引一樣。我是在想。

回答

7

它取決於三件事情:數據庫使用的底層存儲和檢索機制,您要離開的7列的性質以及結果集中返回的行數。

如果您將要離開的7列(或任何數量)的列「便於檢索」,並且返回的行數很少,那麼我期望的效果很小。如果這些列是「昂貴的」(例如,它們很大,或者它們是需要引用另一個永遠不會緩存的文件的BLOB),並且/或者您正在檢索很多行,那麼您可能會期望獲得顯着的改進。多少取決於在特定數據庫中檢索信息並在內存中進行彙編的成本。

除了速度之外,還有其他一些原因,順便說一句,在檢索信息時使用命名列與絕對知道某些列包含在結果集中並且列按照您希望使用它們的期望順序英寸

-1

你爲什麼不嘗試一下,讓我們知道?

這一切都將取決於多少列和它們的寬度。

更好的是,你是否有實際的性能問題?告訴我們你的實際問題是什麼,並告訴我們代碼,然後我們可以建議潛在的改進。可能還有其他的改進要比擔心SELECT *和SELECT字段列表要好得多。

1

我期望看到的主要區別是網絡流量減少。如果任何一列很大,則可能需要一些時間進行傳輸,如果您不顯示它們,這當然是一種完全浪費。

如果您的數據庫庫通過索引(而不是名稱)引用列,這也是非常重要的,因爲如果列順序在數據庫中更改,它將破壞代碼。

編碼風格明智,它允許您查看代碼的其餘部分將使用哪些列,而無需閱讀它。

1

嗯,在一個簡單的實驗中,我驚訝於它造成了多大的差異。

我只是做有三個變化一個簡單的查詢:

  1. SELECT *
  2. 選擇是主鍵字段。 (它可能會直接從索引中得到這個,而實際上沒有讀取記錄)
  3. 選擇一個非關鍵字段。

我用了一個有很多字段的表 - 其中72個 - 包括一個CLOB。該查詢只是where子句中的一個條件選擇。

結果:

 
Run *  Key Non-key 
1 .647 .020 .028 
2 .599 .041 .014 
3 .321 .019 .027 
avg .522 .027 .023 

重點與非重點似乎沒有關係。 (這令我感到驚訝。)但是隻檢索一個字段與選擇*保存了95%的運行時間!

當然這是一個表的一個小實驗。可能有許多相關因素。我當然不會聲稱,通過不使用select *,您總會將運行時間減少95%!但它遠遠超出我的預期。

+0

您是否嘗試先運行Non-Key或Key查詢,以確保它們與'*'相比沒有緩存好處?令人驚訝的是差異如此之大。 – 2010-10-05 22:28:23

+0

考慮到非關鍵列在第2次運行中比關鍵列回來要快得多(假設這不是錯字),我認爲緩存與速度的某些差異有關。 – 2010-10-05 23:00:24

+0

@Jonathan:我以不同的順序多次運行它們,以避免因緩存而導致誤導結果。我連續兩次跑每一個,看看我是否會第二次得到不同的結果等。除了緩存另一個明顯的問題是什麼碰巧同時觸及數據庫。我當然不會聲稱我在這裏的結果是明確的 - 只是有趣的。 – Jay 2010-10-06 14:06:58

1

當比較13 vs 20字段時,如果剩下的7個字段不是CLOB/BLOB等字段,我希望看到沒有明顯的性能增益。 I/O是主要的數據庫瓶頸(大多數數據庫系統是I/O綁定的),所以你可能會認爲你會把執行時間縮短到原始查詢執行時間的13/20(因爲你需要的數據少得多) ),但由於普通字段存儲在相同的物理結構中(通常字段連續排列)並且文件系統讀取整個塊,所以您的磁盤頭將讀取相同數量的數據(假設所有20個字段小於塊大小;情況可以改變,如果一個記錄的大小比你的文件系統塊大)。

SELECT *不好的原因有不同的原因 - 系統的穩定性。

如果您在錯誤的地方使用SELECT *,那麼對基礎表的更改可能會意外地破壞您的系統(主要是以後的時間,如果事情破裂,通常情況下它們會更快破壞)。如果規範化數據(將列從一個表格移動到另一個表格,同時保持相同的名稱),這尤其可能是有利的。在這種情況下,如果您在視圖中鏈接SELECT *,並且鏈接了您的視圖,那麼您實際上可能不會收到任何錯誤,但具有(實質上)不同的最終結果。

-1

選擇*表示數據庫必須花時間查找字段。如果你不需要所有這些字段(並且任何時候你有一個內部聯接,你不需要重複加入字段!),那麼你就是在浪費服務器資源來獲取數據和網絡資源來傳輸數據。您可能也在浪費內存來保存記錄集來處理它。儘管一個查詢的性能改進可能很小,但查詢運行了多少次?而使用這種極其糟糕的技術的人傾向於在任何地方使用它,因此,修復所有這些技術可以成爲一項主要的努力,而不是付出太多的努力。並且指定這些字段有多難?我不知道每個數據庫,但是在SQL Server中,我可以在幾秒鐘內從對象瀏覽器中拖放我想要的內容。因此,使用select *的交易時間不會超過一分鐘的開發時間,因爲每次運行查詢時都會出現性能更差的情況,並且會創建易碎且易受架構更改的問題影響的代碼。我沒有理由在生產代碼中使用select *。