2013-03-29 107 views
0

SELECT聲明:執行期間SQL SELECT語句實際執行的是什麼?

SELECT name 
FROM users 
WHERE address IN (addr_a, addr_b, addr_c, ...); 

我們知道,它會選擇所有的人的名字,其地址是(addr_a,addr_b,addr_c,...)。但是我想知道它在執行這個語句時實際做了什麼。

例如,它是否搜索表中的每個元素以檢查其地址是否在(addr_a,...)中?

如果addr_a,addr_b太長,是否會減慢搜索過程?

有沒有關於推薦這些東西的材料?

編輯:我沒有指定RDBMS,因爲我想知道盡可能多的SQL實現。

再次編輯:在這裏我得到了有關MySQL和SQL Server的答案,我接受了「SQL Server」之一,因爲它是一個詳細的答案。歡迎索取關於其他RDBMS的更多答案。

+0

你爲什麼不用'喜歡'? –

+0

@Praveen我認爲'addr_x's這裏是實際地址的佔位符。 –

+0

這取決於是否創建了「地址」索引 – arunmoezhi

回答

3

由於您尚未指定哪個RDBMS是您的問題,因此我將編寫它如何在SQL Server上工作,嘗試簡化它並避免很多技術問題。它可能在不同的系統上相同或非常相似,但也可能完全不同。

什麼SQL服務器將會與您的查詢

`SELECT name FROM users WHERE address IN (addr_a, addr_b, addr_c, ...);` 

做幾乎完全取決於你在一個表上什麼樣的指標。這裏有3種基本方案:

方案1(良好指標)

如果有所謂Covering Index,這意味着無論是在上addressaddress或非聚集索引PK或聚集索引其中包括name,SQL Server將執行一些名爲Index Seek的操作。這意味着它將通過索引的樹狀結構並快速找出所需的確切行(或找到它不存在)。由於name列也包含在索引中,因此它將讀取並從那裏返回。

方案2(不那麼好的指數)

這是當你有列address,其中不包括列name指數的情況。您可能會經常在一列中找到這些索引,但很快你會發現它們在大多數情況下都毫無用處。你希望SQL Server能夠通過你的索引結構(seek)並快速找到包含你的地址的行。但是,由於name列現在不存在,因此它只能獲取row實際所在的rowID(或PK),因此它將爲每個返回的行額外讀取另一個索引或表,以查找您的行並檢索名稱。由於這需要讀取3次以上的情景1,因此SQL Server通常不會認爲僅通過表的所有行而不是使用索引便宜。那就是在場景中解釋3

方案3(無可用指數)

,如果你沒有在所有索引或列地址沒有索引會發生這種情況。簡單地說,SQL Server會遍歷所有行並檢查每條行的條件。這稱爲Index Scan(或者如果根本沒有索引,則爲Table Scan)。通常情況下最糟糕的情況是 ,而且最慢。

希望有助於澄清事情。

至於另一個關於長字符串放慢的子問題 - 對於這種情況的答案可能是'可能不多'。當SQl服務器比較兩個字符串時,它會逐個字符,因此如果兩個字符串的首字母不同,則不會進一步檢查。但是,如果你在你的字符串開頭加上通配符%,即:WHERE address LIKE '%addr_a' SQL Server將不得不檢查列中每個字符串的每個字符,因此工作速度要慢得多。

2

documentation正確地解釋了它的功能。

如果所有值都是常量,則根據expr的類型對它們進行評估並進行排序。然後搜索該項目是使用二進制搜索完成的。

因此,參數的順序實際上並不重要,因爲無論如何MySQL將它們排序。

+0

感謝您的回答。它有助於! –

1

@Xu:爲選擇查詢創建一個執行計劃,並根據該計劃執行最終執行。請查閱與Execution Plan相關的基本文檔以獲取更多詳細信息。

+0

感謝您的鏈接!它有助於! –

+0

@徐家灣:很棒.... – Sukane