關於SQL中SELECT *(星號)的危害論


聽聞有許多人是禁止開發人員在SQL中使用SELECT *的,這里翻譯一下StackOverflow的一篇提問,個人認為相當客觀

【SELECT *】危害主要有以下幾點:

  • 給數據消費者傳數據的低效。當你SELECT *后常常你會從數據庫查詢出比你應用的功能實際需要過多的列,這還可能導致多余數據從數據到服務端到客戶端,從而導致機器負擔的增加,同樣地網絡傳輸也會增加負擔。特別當數據表增加了新列,但是功能實現那根本又不需要。
  • 索引問題。想象一下這樣一個場景:你需要調一個Query調到一定的高性能。如果你用了SELECT *然后返回全部列超過了你需要的列,服務端經常需要為接收你的數據而消耗代價更多的函數而本來是不用的。舉個例子,你不可能簡簡單單創建一個覆蓋你SELECT出來全部列的索引,即使你這樣做了(包含全部列,想想都可怕),下一個挖坑人又在數據表中增加了新的列就導致你原本已覆蓋的索引無法優化了,然后你會驚奇地發現你的Query性能噗噗噗地下降,又沒有明顯的原因。
  • 綁定問題。當你SELECT *之后,有可能查詢到來自兩張表但是名稱一樣的列。這樣可能會引起數據綁定端或者功能點崩潰,想想返回來有兩列數據都是ID,誰TM知道用哪一列?SELECT *還可能攪亂視圖(部分數據庫、版本)——當底層數據表結構改變,視圖又沒有新建,視圖的數據可能會返回無意義的數據(名稱亂不好維護?)。最慘的,你能折騰好以你命名的列,但新來的挖坑人要加入列的時候就不知道他應該如何命名列名才不會與你已經埋好的列名沖突了。

 但並不是說【SELECT *】只有壞處,以下用例就可以寬泛地使用:

  • 臨時查詢。當調試東西,特別是某一表自己不熟悉的時,SELECT *就顯得很友好了。自己就不用先研究一番這表有啥表明了。這樣表的列名越長SELECT *加分就越高。
  • 當*表示一行。在下面的用例中SELECT *沒啥問題的——之前也有謠傳這樣寫是性能殺手,也許這傳說幾年前還有點說服力,但是現在不是:
    SELECT COUNT(*) FROM table;
    在此用例中“*”表示“數一下行數”,如果你用列名替代這表示要數一下列對應值不為NULL的行數。對我來說,COUNT(*)才是本質意義的數行數,這樣你也避開了擦邊案例(例如聚合搜索中應被消除的NULL值)【譯者覺得還是COUNT(Id)或者COUNT(主鍵)靠譜,這里只是說明數行數的情況,即SELECT * 代表一行時使用沒啥毛病】
    以下類型的Query也是一樣的:
    SELECT a.ID FROM TableA a
    WHERE EXISTS (
        SELECT *
        FROM TableB b
        WHERE b.ID = a.B_ID);
    在任何合格的數據庫中,“*”就是表示“一行”,不管你在子查詢中放了啥。一些人用在SELECT中用ID或者數字1,在我看來在這些約定相當的扯淡。你的意思是要“數行數”,“*”就是用來干這個的。做這些查詢優化的知道這個的都是智者。(實際上,我只知道SQL Server和Oracle就是這樣的)


免責聲明!

本站轉載的文章為個人學習借鑒使用,本站對版權不負任何法律責任。如果侵犯了您的隱私權益,請聯系本站郵箱yoyou2525@163.com刪除。



 
粵ICP備18138465號   © 2018-2025 CODEPRJ.COM