天天看點

索引存儲

對于索引存儲,2008開始有兩種優化方式,都是通過去除重複的資料減少存放的空間,使得原有的存放空間減少。更少的空間意味着更少的頁,更少的頁意味着查詢過程中更少的I/O請求。分别為行壓縮和頁壓縮

1.行壓縮

第一種:降低行的體積。行壓縮通過改變行的存儲形式來達到目的,可以用在堆或者B_Tree上,啟用行壓縮,對應的一下功能會被啟用。

行的原資料該表

定長資料會以變長格式存放

數值型資料類型也會存放成變長格式

--建立兩個測試表作為對比

IF OBJECT_ID('dbo.NoCompression') IS NOT NULL
    DROP TABLE dbo.NoCompression
IF OBJECT_ID('dbo.RowCompression') IS NOT NULL
    DROP TABLE dbo.RowCompression
SELECT  SalesOrderID ,
        SalesOrderDetailID ,
        CarrierTrackingNumber ,
        OrderQty ,
        ProductID ,
        SpecialOfferID ,
        UnitPrice ,
        UnitPriceDiscount ,
        LineTotal ,
        rowguid ,
        ModifiedDate
INTO    dbo.NoCompression
FROM    Sales.SalesOrderDetail
SELECT  SalesOrderID ,
        SalesOrderDetailID ,
        CarrierTrackingNumber ,
        OrderQty ,
        ProductID ,
        SpecialOfferID ,
        UnitPrice ,
        UnitPriceDiscount ,
        LineTotal ,
        rowguid ,
        ModifiedDate
INTO    dbo.RowCompression
FROM    Sales.SalesOrderDetail      

 壓縮功能是在CREATE 或ALTER INDEX語句的DATA_COMPRESSION上實作,壓縮可以用于聚集和非聚集索引上。

下面的語句是行壓縮,大概壓縮了33%的空間

--沒有壓縮
CREATE CLUSTERED INDEX CLIX_NoCompression ON dbo.NoCompression
(SalesOrderID, SalesOrderDetailID);
--行壓縮
CREATE CLUSTERED INDEX CLIX_RowCompression ON dbo.RowCompression
(SalesOrderID, SalesOrderDetailID)
WITH (DATA_COMPRESSION = ROW);
--檢查使用的頁
SELECT  OBJECT_NAME(object_id) AS table_name ,
        in_row_reserved_page_count
FROM    sys.dm_db_partition_stats
WHERE   object_id IN ( OBJECT_ID('dbo.NoCompression'),
                       OBJECT_ID('dbo.RowCompression') )      

 有無行壓縮的頁數:

索引存儲

壓縮并不僅僅帶來存儲空間的減少,還能通過減少資料頁的方式提高查詢性能。

SET STATISTICS IO ON 
             SELECT SalesOrderID,SalesOrderDetailID ,
                     CarrierTrackingNumber  FROM dbo.NoCompression
             WHERE salesorderID BETWEEN 51500 AND 5200

             SELECT SalesOrderID,SalesOrderDetailID ,
                     CarrierTrackingNumber  FROM dbo.RowCompression
             WHERE salesorderID BETWEEN 51500 AND 5200
             SET STATISTICS IO OFF      

 對進行壓縮時,需要考慮以下情況

1.壓縮的前提是應該是對大表進行操作,

2.如果最大的函數超過了8060bytes,則壓縮不能進行

3.非聚集索引不會繼承堆或者聚集索引上的壓縮位置。每個都需要手動進行

4.壓縮時高頻CPU開銷的操作,不能頻繁的進行

二。頁壓縮

頁壓縮也可以在堆和B-Tree結構中進行。頁壓縮通常比行壓縮更有效,因為他包含了行壓縮,字首壓縮和字典壓縮。

在進行頁壓縮前,會先進行行壓縮,然後在對頁中字首相同的資料進行壓縮。

--建立測試表:

IF OBJECT_ID('dbo.PageCompression') IS NOT NULL
    DROP TABLE dbo.PageCompression
SELECT SalesOrderID
    ,SalesOrderDetailID
    ,CarrierTrackingNumber
    ,OrderQty
    ,ProductID
    ,SpecialOfferID
    ,UnitPrice
    ,UnitPriceDiscount
    ,LineTotal
    ,rowguid
    ,ModifiedDate
INTO dbo.PageCompression
FROM Sales.SalesOrderDetail      

 進行壓縮處理:

CREATE CLUSTERED INDEX CLIX_PageCompression ON dbo.PageCompression
(SalesOrderID, SalesOrderDetailID)
WITH (DATA_COMPRESSION = PAGE);
SELECT  OBJECT_NAME(object_id) AS table_name ,
        in_row_reserved_page_count
FROM    sys.dm_db_partition_stats
WHERE   object_id IN ( OBJECT_ID('dbo.NoCompression'),
                       OBJECT_ID('dbo.PageCompression') )      
索引存儲

執行查詢:

SET STATISTICS IO ON 
                       SELECT SalesOrderID,SalesOrderDetailID
    ,CarrierTrackingNumber FROM dbo.PageCompression
                       WHERE SalesOrderID BETWEEN 51500 AND 5200
SET STATISTICS IO OFF      

 索引視圖:

由于權限原因,查詢可能不會傳回很多資料,這時候視圖可能作為一種候選方案,對于僅查詢的靜态資料,建立索引視圖也是一個很好的方案。

不用索引視圖的情況

SET STATISTICS IO ON
             SELECT  
       psc.Name,
       SUM(sod.LineTotal) AS SumLIneTotal,
       SUM(sod.OrderQty) AS SumOrderQty,
       AVG(sod.UnitPrice) AS AvgUnitPrice
        FROM Sales.SalesOrderDetail sod
       INNER JOIN Production.Product p ON sod.ProductID=p.ProductID
       INNER JOIN Production.ProductSubcategory psc ON p.ProductSubcategoryID=psc.ProductSubcategoryID
       GROUP BY psc.Name
       ORDER BY psc.Name      
索引存儲
索引存儲

建立索引視圖:

CREATE VIEW dbo.ProductSubcategorySummry
       --用于建立索引視圖
       WITH  SCHEMABINDING
       AS
             SELECT 
       psc.Name,
       SUM(sod.LineTotal) AS SumLIneTotal,
       SUM(sod.OrderQty) AS SumOrderQty,
       AVG(sod.UnitPrice) AS AvgUnitPrice
       FROM Sales.SalesOrderDetail sod
       INNER JOIN Production.Product p ON sod.ProductID =p.ProductID
       INNER JOIN production.ProductSubcategory psc ON p.ProductSubcategoryID=psc.ProductSubcategoryID GROUP BY psc.Name;      
--建立聚集索引
       CREATE UNIQUE CLUSTERED INDEX CLIX_ProductSubcategorySummay ON dbo.ProductSubcategorySummry(Name)

       SET STATISTICS IO  ON 
       SELECT name,SumLineTotal,SumOrderQty,TotalUnitPrice/Occurances AS AvgUnitPrice FROM dbo.ProductSubcategorySummry 
       ORDER BY name      

 在使用索引視圖後,邏輯讀下降了很多

索引視圖在需要将多個表關聯到一個單元中時非常有效,可以降低關聯時的IO請求

索引視圖的限制條件:

1.視圖中所有列必須是确定的

2.索引視圖必須使用SCHEMA_BINDING選項

3.聚集索引必須使用unique選項

4.引用的表必須具有帶有架構名

5.某些彙總函數如AVG(),不能用于索引視圖