顯示具有 MSSQL 標籤的文章。 顯示所有文章
顯示具有 MSSQL 標籤的文章。 顯示所有文章

2015年5月27日 星期三

檢查資料庫之資料表索引是否應該重建或重組

檢查資料庫之資料表索引是否應該重建或重組

MSSQL 檢查資料庫之資料表索引是否應該重建或重組

本文是學習筆記,內容來自於 [1] ,摘錄語法重點

目的

索引維護,改善效能

範例

檢查索引狀態

引用 [1] 之範例

SELECT OBJECT_NAME(dt.object_id) as TableName  ,
   si.name,
   dt.avg_fragmentation_in_percent,
   dt.avg_page_space_used_in_percent
FROM
   (SELECT object_id   ,
   index_id,
   avg_fragmentation_in_percent,
   avg_page_space_used_in_percent
   FROMsys.dm_db_index_physical_stats (DB_ID(), NULL, NULL, NULL, 'DETAILED')
   WHERE   index_id <> 0
   ) AS dt --does not return information about heaps
   INNER JOIN sys.indexes si
   ON si.object_id = dt.object_id
  AND si.index_id  = dt.index_id

根據 [1] 之說明,重建或重組之建議條件如下

索引重組的時機

  • 檢查 External fragmentation 部分

    當 avg_fragmentation_in_percent 的值介於 10 到 15 之間
    
  • 檢查 Internal fragmentation 部分

    當 avg_page_space_used_in_percent 的值介於 60 到 75 之間
    

索引重建的時機

  • 檢查 External fragmentation 部分

    當 avg_fragmentation_in_percent 的值大於 15
    
  • 檢查 Internal fragmentation 部分

    當 avg_page_space_used_in_percent 的值小於 60
    

重建索引

引用 [1] 之範例, 僅檢查 External Fragmentation

SELECT 'ALTER INDEX [' + ix.name + '] ON [' + s.name + '].[' + t.name + '] ' +
   CASE
  WHEN ps.avg_fragmentation_in_percent > 15
  THEN 'REBUILD'
  ELSE 'REORGANIZE'
   END +
   CASE
  WHEN pc.partition_count > 1
  THEN ' PARTITION = ' + CAST(ps.partition_number AS nvarchar(MAX))
  ELSE ''
   END,
   avg_fragmentation_in_percent
FROM   sys.indexes AS ix
   INNER JOIN sys.tables t
   ON t.object_id = ix.object_id
   INNER JOIN sys.schemas s
   ON t.schema_id = s.schema_id
   INNER JOIN
  (SELECT object_id   ,
  index_id,
  avg_fragmentation_in_percent,
  partition_number
  FROMsys.dm_db_index_physical_stats (DB_ID(), NULL, NULL, NULL, NULL)
  ) ps
   ON t.object_id = ps.object_id
  AND ix.index_id = ps.index_id
   INNER JOIN
  (SELECT  object_id,
   index_id ,
   COUNT(DISTINCT partition_number) AS partition_count
  FROM sys.partitions
  GROUP BY object_id,
   index_id
  ) pc
   ON t.object_id  = pc.object_id
  AND ix.index_id  = pc.index_id
WHERE  ps.avg_fragmentation_in_percent > 10
   AND ix.name IS NOT NULL

有需要重建的索引,其重建索引語法會被列出來,複製後執行即可完成索引之維護

參考資料介紹

[1] 介紹索引重建的語法及重建時機

[2] 介紹什麼是索引,其原理,資料結構,索引類型,等等知識。 (含範例),這篇很詳細,篇末還有索引維謢的線上教學影片

參考資料

[1] The Will will Web - 讓 SQL Server 告訴你有哪些索引應該被重建或重組

[2] TechNet 台灣部落格 - 如何寫出高效能 TSQL - 關於索引不可不知道的事

2015年5月26日 星期二

MS SQL Trigger Example

MSSQL_Trigger_Demo

MS SQL Trigger Demo

使用時機

資料表異動時,想記錄異動的資料列。參考 [1] 有很棒的說明。

範例

已知 :

有一個資料表 [MyUser],你想要記錄該資料表的異動狀態,並將該異動狀態記錄在 [MyUser_Log] 資料表中

[MyUser] 資料表設計如下

CREATE TABLE [dbo].[MyUser](
    [SN] [int] IDENTITY(1,1) NOT NULL,
    [Name] [nvarchar](50) NOT NULL, 
 CONSTRAINT [PK_MyUser] PRIMARY KEY CLUSTERED 
(
    [SN] ASC
)WITH (PAD_INDEX = OFF, STATISTICS_NORECOMPUTE = OFF, IGNORE_DUP_KEY = OFF, ALLOW_ROW_LOCKS = ON, ALLOW_PAGE_LOCKS = ON) ON [PRIMARY]
) ON [PRIMARY]

解題

Step 1. 建立 [MyUser_log] 資料表,記錄異動狀態,包含異動狀態又時間,設計如下

CREATE TABLE [dbo].[MyUser_Log](
    [SN] [int],
    [Name] [nvarchar](50),  
    [ST] [nvarchar](50),
    [CreatedDate] [datetime]
    )

其中,CreateDate 記錄異動的時間,ST 記錄異動狀態

Step 2. 建立 [MyUser] 資料表的 Trigger, 如下

CREATE Trigger [dbo].[MyUser_I_U_D] ON [dbo].[MyUser] AFTER UPDATE, INSERT, DELETE
AS
BEGIN
    --INSERT
    IF EXISTS(SELECT 1 FROM inserted) AND NOT EXISTS(SELECT 1 FROM deleted)
    BEGIN
        Insert Into MyUser_Log Select *, N'After Inserted', getdate() From Inserted
    END   

    -- UPDATE
IF EXISTS(SELECT 1 FROM inserted) AND EXISTS(SELECT 1 FROM deleted)
BEGIN
        Insert Into MyUser_Log Select *, N'Before Update', getdate() From deleted
        Insert Into MyUser_Log Select *, N'After Updated', getdate() From Inserted      
    END   

    --DELETE 
   IF NOT EXISTS(SELECT 1 FROM inserted) AND EXISTS(SELECT 1 FROM deleted)
   BEGIN
    Insert Into MyUser_Log Select *, N'Before Deleted', getdate() From deleted
   END
END

測試

新增

--新增一筆資料
  INSERT INTO MyUser(Name)VALUES(N'J')
  SELECT * FROM MyUser_Log

修改

  --更改一筆資料
  UPDATE MyUser SET Name = N'M'
  SELECT * FROM MyUser_Log

刪除

  --刪除一筆資料
  DELETE MyUser
  SELECT * FROM MyUser_Log

參考資料介紹

[1] 說明 Trigger 用途,介紹 Trigger 運作原理,Trigger 使用範例 (資料儲存使用 XML) 及 XML 查詢方式

[2] 說明 Trigger 用途, Trigger 範例, Step by Step (圖文並茂)

[3] MSDN Trigger 語法

參考資料

[1] 軟體開發的天空-使用 Trigger 紀錄資料表的新增、修改、刪除的行為

[2] SQL Server,Trigger 的簡單範例,以「訂單的流程系統」為例

[3] MSDN-CREATE TRIGGER (Transact-SQL)