国产探花免费观看_亚洲丰满少妇自慰呻吟_97日韩有码在线_资源在线日韩欧美_一区二区精品毛片,辰东完美世界有声小说,欢乐颂第一季,yy玄幻小说排行榜完本

首頁 > 開發 > 綜合 > 正文

使用正確的篩選參數來提高查詢性能

2024-07-21 02:46:25
字體:
來源:轉載
供稿:網友
使用正確的篩選參數來提高查詢性能

在今天的文章里我想談下SQL Server里與索引相關的特殊性能問題。

問題描述

假設下列的簡單查詢,在你的日常SQL Server里,這樣的查詢你已經看到過幾百遍了:

1 -- Results in an Index Scan2 SELECT * FROM Sales.SalesOrderHeader3 WHERE YEAR(OrderDate) = 2005 AND MONTH(OrderDate) = 74 GO

用那個簡單查詢,我們請求在特定年份特定月份里的銷售信息。并不復雜。遺憾的是這個查詢性能很差——即使在OrderDate列使用了非聚集索引。當你查看執行計劃時,你會看到查詢優化器選擇了在OrderDate列上的非聚集索引,但遺憾的是SQL Server進行的索引的全掃描,而不是高效的查找操作。

這真不是SQL Server的局限性,而是關系數據庫的工作和思考方式:)只要你在索引列上使用了表達式(函數調用,計算)(即所謂的篩選參數(Search Argument)),數據庫引擎必須去掃描那個索引,而不是進行查找操作。

解決方法

在執行計劃里為了獲得可擴展的查找操作,你必須要換種方式重寫你的查詢來避免DATEPART函數的調用:

1 -- Results in an Index Seek2 SELECT * FROM Sales.SalesOrderHeader3 WHERE OrderDate >= '20050701' AND OrderDate < '20050801'4 GO

從重寫的查詢可以看到,查詢返回同樣的結果,但我們已經剔除了DATEPART函數的調用。當你查看執行計劃時,你會看到SQL Server進行了查找操作——在那個情況下,這個是所謂的局部范圍掃描(Partial Range Scan):SQL Server查找到第1個值,然后掃描到請求范圍的最有值。如果你想在索引列上下文調用函數,你必須保證在查詢里,這些函數調用的執行在你列的右側。我們來看一個具體的例子。下面查詢把CreditCardID索引列轉化為CHAR(4)數據類型:

1 -- Results in an Index Scan2 SELECT * FROM Sales.SalesOrderHeader3 WHERE CAST(CreditCardID AS CHAR(4)) = '1347'4 GO

當你仔細看執行計劃時,你會看到SQL Server再次掃描整個非聚集索引。如果你的表越來越大,這是真不能擴展的。如果你在查詢里在你索引列的右側執行轉化,你就可以在索引列上剔除函數調用,SQL Server就可以進行查找操作:

1 -- Results in an Index Seek2 SELECT * FROM Sales.SalesOrderHeader3 WHERE CreditCardID = CAST('1347' AS INT)4 GO

小結

從這篇文章里,你可以看到,在你的索引列里不直接調用任何函數或間接調用函數是非常重要的。不然的話SQL Server會掃描你的索引,而不是進行高效的查找操作。而且當你表越來越大時,掃描從不擴展。

如果你碰到這個特殊行為的其他好例子,想分享的話,歡迎留言。

感謝關注。


發表評論 共有條評論
用戶名: 密碼:
驗證碼: 匿名發表
主站蜘蛛池模板: 宁海县| 武宣县| 唐海县| 九寨沟县| 昭觉县| 汽车| 康保县| 遂溪县| 池州市| 静海县| 甘孜县| 抚远县| 神木县| 磐安县| 芒康县| 揭西县| 任丘市| 凯里市| 河北省| 博爱县| 家居| 镇巴县| 陆川县| 宜城市| 泗水县| 宁都县| 铁岭县| 桓仁| 勃利县| 东兰县| 清水河县| 东兰县| 吉木萨尔县| 德令哈市| 资兴市| 台山市| 牡丹江市| 明星| 红安县| 双辽市| 喀喇|