最近幫朋友搞一個電子黃頁的基目,里面有幾百萬數據,其中一個表包含了以下幾個字段:
ID(主鍵,標識,自增長int,索引),
CityID(城市ID,int,索引),
CateID(類別ID,int,索引),
CateParentID(父類別ID,int,索引)。
類別只有2級,所以,為了加快查詢效率,索性把大類ID和小類ID都單獨列為字段。
按照習慣,在查詢某個大類ID時候,例如查詢大類ID為112的第一頁黃頁數據時,用了常用的語句
select top 10 * from E_Table where CateParentID=112
雖然CateParentID做了索引,雖然只是查詢10條數據,但是擁有近400萬條記錄的情況下,這個簡單的查詢居然用了45秒才得到結果。以致搜索引擎遲遲無法更新網頁的快照。真是急煞我也。
之后按照某高人指點:若無法從該索引篩選出低於總數據量1%的結果,則不應該添加索引,去除了CateParentID的索引。然而情況並沒有好轉,仍然維持在42秒左右。
但是條件一旦換成是CateID=xxx的時候,速度總是出奇的快。CateParentID和CateID都是int型,且都有索引,區別怎么會這么大呢?在操作上,CateID列是在創建表的時候添加的,而CateParentID列是在數據全部進表后才添加的,難道僅僅是因為原生的和后加的數據列竟然會被MS區別對待?
就數據量而言,400萬的數據對於MS SQL來說應該算是小兒科了,有同事建議我采用“水平切割”,即按大類進行分表,但我認為區區幾百萬就采用分表分明是種逃避。
於是我不甘心這么簡潔的語句就這樣死掉,換成這樣
select top 10 ID from E_Table where CateParentID=112 之后滿懷期待地等了近40+秒...
最后一絲希望破滅,於是趕緊另想辦法,今天是禮拜三,百度刷新快照的好日子。我想到之前做隨機取數據的時候,select ID from table取所有ID到內存,之后再隨機N條,這個取的過程非常快,盡管數據量也非常大,“何不把CateParentID和ID先取來,再給條件,無視其它數據”我這樣想着,於是有了下面的語句:
select * from [E_Table] where ID in (
select top 10 [t0].[ID] from (
select ID,CateParentID from [E_Table]
) as [t0] where [t0].[CateParentID]=112
)
這個運行倒是很快,在本地300毫秒內返回結果,但是要注意的是查詢條件需要的列必須在第一次就全部取到(即最底層),另外要注意如果有全文索引,可以把全文索引的條件寫在最外層,速度也是非常快!
結論:(1)竊以為,int型數據+索引在大數據量時對查詢速度的幫助不大。
(2)竊以為,單條簡潔的SQL語句未必比嵌套的快。
(3)竊以為,原生的列和在大量數據之后附加的列,在同等條件查詢速度上,貌似是親媽生的和后媽生的。純屬猜想,該結論尚未得到證實。希望有行家里手加以指正,小弟感激不盡。
(4)竊以為,這個標題和內容還是有點不相符,但是我無法用精練的話概括我的內容.
