前言
上一節我們詳細講解了計算列以及計算列持久化的問題,本節我們依然如前面講解來看看二者查詢性能問題,簡短的內容,深入的理解,Always to review the basics。
持久化計算列比非持久化計算列性能要好
我們開始創建兩個一樣的表並都插入100條數據來進行比較,對於計算列我們重新進行創建計算列和非計算列持久化。
CREATE TABLE [dbo].[ComputeColumnCompare] (ID INT, FirstName VARCHAR(100), LastName CHAR(8000)) GO
INSERT INTO [dbo].[ComputeColumnCompare] (ID,FirstName,LastName) SELECT TOP 100 ROW_NUMBER() OVER (ORDER BY a.name) RowID, 'Bob', CASE WHEN ROW_NUMBER() OVER (ORDER BY a.name)%2 = 1 THEN 'Smith' ELSE 'Brown' END FROM sys.all_objects a CROSS JOIN sys.all_objects b GO
在ComputeColumn表上創建計算列
USE TSQL2012 GO ALTER TABLE dbo.ComputeColumn ADD FullName AS POWER(LEN(LEFT((FirstName+CAST(ID AS VARCHAR(100))),3)), 12) GO
在ComputeColumnCompare表上創建計算持久化列
USE TSQL2012 GO ALTER TABLE dbo.ComputeColumnCompare ADD FullName_P AS POWER(LEN(LEFT((FirstName+CAST(ID AS VARCHAR(100))),3)), 12) PERSISTED GO
此時我們來運行兩個表對計算列和計算列持久化列的查詢
USE TSQL2012 GO SELECT FullName FROM dbo.ComputeColumn WHERE FullName = 531441 GO SELECT FullName_P FROM dbo.ComputeColumnCompare WHERE FullName_P = 531441 GO
此時二者的開銷是一樣的,只是非持久化列多了一個Compute Scalar操作,主要是因為它計算值是在運行時,此時我們來看看操作成本。
我們看到二者性能還是有一點差異,所以我們能夠知道如果計算操作比較復雜時利用持久化來提前進行計算性能會比非持久化列更好。是不是所有情況下持久化列性能都比持久化列性能要好呢?繼續往下看。
非持久化計算列比持久化計算列性能要好
我們再來創建測試表並插入1萬條數據來進行比較。
USE TSQL2012 GO CREATE TABLE [dbo].[ComputeColumn] (ID INT, FirstName VARCHAR(100), LastName CHAR(800)) GO CREATE TABLE [dbo].[ComputeColumnCompare](ID INT, FirstName VARCHAR(100), LastName CHAR(800)) GO
USE TSQL2012 GO INSERT INTO [dbo].[ComputeColumn](ID,FirstName,LastName) SELECT TOP 10000 ROW_NUMBER() OVER (ORDER BY a.name) RowID, 'Bob', CASE WHEN ROW_NUMBER() OVER (ORDER BY a.name)%2 = 1 THEN 'Smith' ELSE 'Brown' END FROM sys.all_objects a CROSS JOIN sys.all_objects b GO
INSERT INTO [dbo].[ComputeColumnCompare](ID,FirstName,LastName) SELECT TOP 10000 ROW_NUMBER() OVER (ORDER BY a.name) RowID, 'Bob', CASE WHEN ROW_NUMBER() OVER (ORDER BY a.name)%2 = 1 THEN 'Smith' ELSE 'Brown' END FROM sys.all_objects a CROSS JOIN sys.all_objects b GO
接下來在兩表上創建持久化計算列和非持久化計算列
USE TSQL2012 GO ALTER TABLE dbo.ComputeColumn ADD FullName AS (FirstName+' '+LastName) GO ALTER TABLE dbo.ComputeColumnCompare ADD FullName_P AS (FirstName+' '+LastName) PERSISTED GO
最后我們進行查詢看看查詢計划結果
USE TSQL2012 GO SELECT FullName FROM dbo.ComputeColumn WHERE FullName = 'Bob Smith' GO SELECT FullName_P FROM dbo.ComputeColumnCompare WHERE FullName_P = 'Bob Smith' GO
到這里我們發現非持久化計算列性能要比持久化計算列性能要好,和上面對照的話我已經明確進行了標記定義列的大小以及插入行的多少是不同的,所以對於持久化列和非持久化列二者並沒有絕對性能的誰好誰好,當我們想要看二者誰性能更佳時,我們可能需要考慮定義列的大小、數據行的多少等等。下面我們還看最后一種情況,就是在計算列上來創建索引。
非持久化計算列提高查詢性能
我們繼續創建測試表
USE TSQL2012 GO CREATE TABLE [dbo].[ComputeColumn] (ID INT, FirstName VARCHAR(100), LastName VARCHAR(100)) GO CREATE TABLE [ComputeColumnCompare] (ID INT, FirstName VARCHAR(100), LastName VARCHAR(100)) GO
USE TSQL2012 GO INSERT INTO [dbo].[ComputeColumn] (ID,FirstName,LastName) SELECT TOP 10000 ROW_NUMBER() OVER (ORDER BY a.name) RowID, 'Bob', CASE WHEN ROW_NUMBER() OVER (ORDER BY a.name)%2 = 1 THEN 'Smith' ELSE 'Brown' END FROM sys.all_objects a CROSS JOIN sys.all_objects b GO INSERT INTO [dbo].[ComputeColumnCompare](ID,FirstName,LastName) SELECT TOP 10000 ROW_NUMBER() OVER (ORDER BY a.name) RowID, 'Bob', CASE WHEN ROW_NUMBER() OVER (ORDER BY a.name)%2 = 1 THEN 'Smith' ELSE 'Brown' END FROM sys.all_objects a CROSS JOIN sys.all_objects b GO
在ComputeColumn表上創建計算列並創建一個非聚集索引
ALTER TABLE dbo.ComputeColumn ADD FullName AS (FirstName+' '+LastName) GO CREATE NONCLUSTERED INDEX IX_CompCol_CityTrim ON dbo.ComputeColumn (FullName) GO
在ComputeColumnCompare表上創建計算列
ALTER TABLE dbo.ComputeColumnCompare ADD FullName_P AS (FirstName+' '+LastName) GO
最后查詢兩個表看看查詢計划結果
USE TSQL2012 GO SELECT FullName FROM dbo.ComputeColumn WHERE FullName = 'Bob Smith' GO SELECT FullName_P FROM dbo.ComputeColumnCompare WHERE FullName_P = 'Bob Smith' GO
從上述我們知道對計算列創建一個索引能很好的提高查詢性能,當然了上述僅僅只是返回計算列,若返回其他列的話可能會導致Key Lookup,但是從另外一個角度來講還是能提高查詢性能,為了解決Key Lookup問題建立太多索引也是有問題的,具體情況具體分析吧。這里並沒有比較持久化計算列和非持久化計算列的性能,二者其實是一樣的,就沒有比較了,只是在利用持久化在數據存儲上不同而已。參考資料:【http://blog.sqlauthority.com/2010/08/03/sql-server-computed-column-persisted-and-performance/】
總結
到此我們算是結束了對於計算列以及關於計算列持久的概念和性能的分析,下節我們再看看其他查詢的知識,接着就進入表表達式的學習,簡短的內容,深入的理解,我們下節再會。