ΠŸΡ€Π΅Π³Π»Π΅Π΄ Π½Π° бСзплатния инструмСнт SQLIndexManager

ΠšΠ°ΠΊΡ‚ΠΎ Π·Π½Π°Π΅Ρ‚Π΅, индСкситС играят Π²Π°ΠΆΠ½Π° роля Π² Π‘Π£Π‘Π”, осигурявайки Π±ΡŠΡ€Π·ΠΎ Ρ‚ΡŠΡ€ΡΠ΅Π½Π΅ Π½Π° Π½Π΅ΠΎΠ±Ρ…ΠΎΠ΄ΠΈΠΌΠΈΡ‚Π΅ записи. Π•Ρ‚ΠΎ Π·Π°Ρ‰ΠΎ Π΅ Ρ‚ΠΎΠ»ΠΊΠΎΠ²Π° Π²Π°ΠΆΠ½ΠΎ Π΄Π° Π³ΠΈ обслуТватС Π½Π°Π²Ρ€Π΅ΠΌΠ΅. Π—Π° Π°Π½Π°Π»ΠΈΠ·Π° ΠΈ оптимизацията са изписани доста ΠΌΠ°Ρ‚Π΅Ρ€ΠΈΠ°Π»ΠΈ, Π²ΠΊΠ»ΡŽΡ‡ΠΈΡ‚Π΅Π»Π½ΠΎ ΠΈ Π² Π˜Π½Ρ‚Π΅Ρ€Π½Π΅Ρ‚. НапримСр, Ρ‚Π°Π·ΠΈ Ρ‚Π΅ΠΌΠ° бСшС наскоро ΠΏΡ€Π΅Π³Π»Π΅Π΄Π°Π½Π° Π² Ρ‚Π°Π·ΠΈ публикация.

Има ΠΌΠ½ΠΎΠ³ΠΎ ΠΏΠ»Π°Ρ‚Π΅Π½ΠΈ ΠΈ Π±Π΅Π·ΠΏΠ»Π°Ρ‚Π½ΠΈ Ρ€Π΅ΡˆΠ΅Π½ΠΈΡ Π·Π° Ρ‚ΠΎΠ²Π°. НапримСр, ΠΈΠΌΠ° Π³ΠΎΡ‚ΠΎΠ²Π° Ρ€Π΅ΡˆΠ΅Π½ΠΈΠ΅, Π±Π°Π·ΠΈΡ€Π°Π½ Π½Π° Π°Π΄Π°ΠΏΡ‚ΠΈΠ²Π΅Π½ ΠΌΠ΅Ρ‚ΠΎΠ΄ Π·Π° оптимизация Π½Π° индСкса.

Π‘Π»Π΅Π΄ Ρ‚ΠΎΠ²Π° Π½Π΅ΠΊΠ° Ρ€Π°Π·Π³Π»Π΅Π΄Π°ΠΌΠ΅ Π±Π΅Π·ΠΏΠ»Π°Ρ‚Π½Π°Ρ‚Π° ΠΏΠΎΠΌΠΎΡ‰Π½Π° ΠΏΡ€ΠΎΠ³Ρ€Π°ΠΌΠ° SQLIndexManager, с Π°Π²Ρ‚ΠΎΡ€ Алън Π”Π΅Π½Ρ‚ΡŠΠ½.

ΠžΡΠ½ΠΎΠ²Π½Π°Ρ‚Π° тСхничСска Ρ€Π°Π·Π»ΠΈΠΊΠ° ΠΌΠ΅ΠΆΠ΄Ρƒ SQLIndexManager ΠΈ Ρ€Π΅Π΄ΠΈΡ†Π° Π΄Ρ€ΡƒΠ³ΠΈ Π°Π½Π°Π»ΠΎΠ·ΠΈ Π΅ Π΄Π°Π΄Π΅Π½Π° ΠΎΡ‚ самия Π°Π²Ρ‚ΠΎΡ€ Ρ‚ΡƒΠΊ ΠΈ Ρ‚ΡƒΠΊ.

Π’ Ρ‚Π°Π·ΠΈ статия Ρ‰Π΅ Ρ€Π°Π·Π³Π»Π΅Π΄Π°ΠΌΠ΅ ΠΏΡ€ΠΎΠ΅ΠΊΡ‚Π° ΠΎΡ‚Π²ΡŠΠ½ ΠΈ ΠΎΠΏΠ΅Ρ€Π°Ρ‚ΠΈΠ²Π½ΠΈΡ‚Π΅ Π²ΡŠΠ·ΠΌΠΎΠΆΠ½ΠΎΡΡ‚ΠΈ Π½Π° Ρ‚ΠΎΠ²Π° софтуСрно Ρ€Π΅ΡˆΠ΅Π½ΠΈΠ΅.

ОбсъТданС Π½Π° Ρ‚Π°Π·ΠΈ ΠΏΠΎΠΌΠΎΡ‰Π½Π° ΠΏΡ€ΠΎΠ³Ρ€Π°ΠΌΠ° Ρ‚ΡƒΠΊ.
Π‘ Ρ‚Π΅Ρ‡Π΅Π½ΠΈΠ΅ Π½Π° Π²Ρ€Π΅ΠΌΠ΅Ρ‚ΠΎ ΠΏΠΎΠ²Π΅Ρ‡Π΅Ρ‚ΠΎ ΠΎΡ‚ ΠΊΠΎΠΌΠ΅Π½Ρ‚Π°Ρ€ΠΈΡ‚Π΅ ΠΈ Π³Ρ€Π΅ΡˆΠΊΠΈΡ‚Π΅ бяха ΠΊΠΎΡ€ΠΈΠ³ΠΈΡ€Π°Π½ΠΈ.

И Ρ‚Π°ΠΊΠ°, Π½Π΅ΠΊΠ° сСга Π΄Π° ΠΏΡ€Π΅ΠΌΠΈΠ½Π΅ΠΌ към самата ΠΏΠΎΠΌΠΎΡ‰Π½Π° ΠΏΡ€ΠΎΠ³Ρ€Π°ΠΌΠ° SQLIndexManager.

ΠŸΡ€ΠΈΠ»ΠΎΠΆΠ΅Π½ΠΈΠ΅Ρ‚ΠΎ Π΅ написано Π½Π° C# .NET Framework 4.5 във Visual Studio 2017 ΠΈ ΠΈΠ·ΠΏΠΎΠ»Π·Π²Π° DevExpress Π·Π° формуляри:

ΠŸΡ€Π΅Π³Π»Π΅Π΄ Π½Π° бСзплатния инструмСнт SQLIndexManager

ΠΈ ΠΈΠ·Π³Π»Π΅ΠΆΠ΄Π° Ρ‚Π°ΠΊΠ°:

ΠŸΡ€Π΅Π³Π»Π΅Π΄ Π½Π° бСзплатния инструмСнт SQLIndexManager

Всички заявки сС Π³Π΅Π½Π΅Ρ€ΠΈΡ€Π°Ρ‚ Π² слСднитС Ρ„Π°ΠΉΠ»ΠΎΠ²Π΅:

  1. индСкс
  2. Π—Π°ΠΏΠΈΡ‚Π²Π°Π½Π΅
  3. QueryEngine
  4. Π˜Π½Ρ„ΠΎΡ€ΠΌΠ°Ρ†ΠΈΡ Π·Π° ΡΡŠΡ€Π²ΡŠΡ€Π°

ΠŸΡ€Π΅Π³Π»Π΅Π΄ Π½Π° бСзплатния инструмСнт SQLIndexManager

ΠŸΡ€ΠΈ ΡΠ²ΡŠΡ€Π·Π²Π°Π½Π΅ към Π±Π°Π·Π° Π΄Π°Π½Π½ΠΈ ΠΈ ΠΈΠ·ΠΏΡ€Π°Ρ‰Π°Π½Π΅ Π½Π° заявки към Π‘Π£Π‘Π” ΠΏΡ€ΠΈΠ»ΠΎΠΆΠ΅Π½ΠΈΠ΅Ρ‚ΠΎ сС подписва, ΠΊΠ°ΠΊΡ‚ΠΎ слСдва:

ApplicationName=”SQLIndexManager”

ΠšΠΎΠ³Π°Ρ‚ΠΎ стартиратС ΠΏΡ€ΠΈΠ»ΠΎΠΆΠ΅Π½ΠΈΠ΅Ρ‚ΠΎ, Ρ‰Π΅ сС ΠΎΡ‚Π²ΠΎΡ€ΠΈ ΠΌΠΎΠ΄Π°Π»Π΅Π½ ΠΏΡ€ΠΎΠ·ΠΎΡ€Π΅Ρ† Π·Π° добавянС Π½Π° Π²Ρ€ΡŠΠ·ΠΊΠ°:
ΠŸΡ€Π΅Π³Π»Π΅Π΄ Π½Π° бСзплатния инструмСнт SQLIndexManager

Π’ΡƒΠΊ Π·Π°Ρ€Π΅ΠΆΠ΄Π°Π½Π΅Ρ‚ΠΎ Π½Π° пълСн списък Π½Π° всички копия Π½Π° MS SQL Server, Π΄ΠΎΡΡ‚ΡŠΠΏΠ½ΠΈ ΠΏΡ€Π΅Π· Π»ΠΎΠΊΠ°Π»Π½ΠΈ ΠΌΡ€Π΅ΠΆΠΈ, всС ΠΎΡ‰Π΅ Π½Π΅ Ρ€Π°Π±ΠΎΡ‚ΠΈ.

ΠœΠΎΠΆΠ΅Ρ‚Π΅ ΡΡŠΡ‰ΠΎ Π΄Π° Π΄ΠΎΠ±Π°Π²ΠΈΡ‚Π΅ Π²Ρ€ΡŠΠ·ΠΊΠ°, ΠΊΠ°Ρ‚ΠΎ ΠΈΠ·ΠΏΠΎΠ»Π·Π²Π°Ρ‚Π΅ Π½Π°ΠΉ-лСвия Π±ΡƒΡ‚ΠΎΠ½ Π² Π³Π»Π°Π²Π½ΠΎΡ‚ΠΎ мСню:

ΠŸΡ€Π΅Π³Π»Π΅Π΄ Π½Π° бСзплатния инструмСнт SQLIndexManager

Π‘Π»Π΅Π΄ Ρ‚ΠΎΠ²Π° Ρ‰Π΅ Π±ΡŠΠ΄Π°Ρ‚ стартирани слСднитС заявки към Π‘Π£Π‘Π”:

  1. ΠŸΠΎΠ»ΡƒΡ‡Π°Π²Π°Π½Π΅ Π½Π° информация Π·Π° Π‘Π£Π‘Π”
    SELECT ProductLevel  = SERVERPROPERTY('ProductLevel')
         , Edition       = SERVERPROPERTY('Edition')
         , ServerVersion = SERVERPROPERTY('ProductVersion')
         , IsSysAdmin    = CAST(IS_SRVROLEMEMBER('sysadmin') AS BIT)
    

  2. ΠŸΠΎΠ»ΡƒΡ‡Π°Π²Π°Π½Π΅ Π½Π° списък с Π½Π°Π»ΠΈΡ‡Π½ΠΈ Π±Π°Π·ΠΈ Π΄Π°Π½Π½ΠΈ с Ρ‚Π΅Ρ…Π½ΠΈΡ‚Π΅ ΠΊΡ€Π°Ρ‚ΠΊΠΈ свойства
    SELECT DatabaseName = t.[name]
         , d.DataSize
         , DataUsedSize  = CAST(NULL AS BIGINT)
         , d.LogSize
         , LogUsedSize   = CAST(NULL AS BIGINT)
         , RecoveryModel = t.recovery_model_desc
         , LogReuseWait  = t.log_reuse_wait_desc
    FROM sys.databases t WITH(NOLOCK)
    LEFT JOIN (
        SELECT [database_id]
             , DataSize = SUM(CASE WHEN [type] = 0 THEN CAST(size AS BIGINT) END)
             , LogSize  = SUM(CASE WHEN [type] = 1 THEN CAST(size AS BIGINT) END)
        FROM sys.master_files WITH(NOLOCK)
        GROUP BY [database_id]
    ) d ON d.[database_id] = t.[database_id]
    WHERE t.[state] = 0
        AND t.[database_id] != 2
        AND ISNULL(HAS_DBACCESS(t.[name]), 1) = 1
    

Π‘Π»Π΅Π΄ изпълнСниС Π½Π° Π³ΠΎΡ€Π½ΠΈΡ‚Π΅ скриптовС Ρ‰Π΅ сС появи ΠΏΡ€ΠΎΠ·ΠΎΡ€Π΅Ρ†, ΡΡŠΠ΄ΡŠΡ€ΠΆΠ°Ρ‰ ΠΊΡ€Π°Ρ‚ΠΊΠ° информация Π·Π° Π±Π°Π·ΠΈΡ‚Π΅ Π΄Π°Π½Π½ΠΈ Π½Π° избрания СкзСмпляр Π½Π° MS SQL Server:

ΠŸΡ€Π΅Π³Π»Π΅Π΄ Π½Π° бСзплатния инструмСнт SQLIndexManager

Π‘Ρ‚Ρ€ΡƒΠ²Π° си Π΄Π° сС ΠΎΡ‚Π±Π΅Π»Π΅ΠΆΠΈ, Ρ‡Π΅ Ρ€Π°Π·ΡˆΠΈΡ€Π΅Π½Π°Ρ‚Π° информация сС ΠΏΠΎΠΊΠ°Π·Π²Π° въз основа Π½Π° ΠΏΡ€Π°Π²Π°. Ако ΠΈΠΌΠ° администратор, слСд ΠΊΠΎΠ΅Ρ‚ΠΎ ΠΌΠΎΠΆΠ΅Ρ‚Π΅ Π΄Π° ΠΈΠ·Π±Π΅Ρ€Π΅Ρ‚Π΅ Π΄Π°Π½Π½ΠΈ ΠΎΡ‚ ΠΈΠ·Π³Π»Π΅Π΄Π° sys.master_files. Ако няма Ρ‚Π°ΠΊΠΈΠ²Π° ΠΏΡ€Π°Π²Π°, Ρ‚ΠΎΠ³Π°Π²Π° просто сС Π²Ρ€ΡŠΡ‰Π°Ρ‚ ΠΏΠΎ-ΠΌΠ°Π»ΠΊΠΎ Π΄Π°Π½Π½ΠΈ, Π·Π° Π΄Π° Π½Π΅ сС забавя заявката.

Π’ΡƒΠΊ трябва Π΄Π° ΠΈΠ·Π±Π΅Ρ€Π΅Ρ‚Π΅ интСрСсуващитС Π²ΠΈ Π±Π°Π·ΠΈ Π΄Π°Π½Π½ΠΈ ΠΈ Π΄Π° ΠΊΠ»ΠΈΠΊΠ½Π΅Ρ‚Π΅ Π²ΡŠΡ€Ρ…Ρƒ Π±ΡƒΡ‚ΠΎΠ½Π° β€žOKβ€œ.

Π‘Π»Π΅Π΄ Ρ‚ΠΎΠ²Π° Ρ‰Π΅ сС изпълни слСдният скрипт Π·Π° всяка ΠΈΠ·Π±Ρ€Π°Π½Π° Π±Π°Π·Π° Π΄Π°Π½Π½ΠΈ, Π·Π° Π΄Π° сС Π°Π½Π°Π»ΠΈΠ·ΠΈΡ€Π° ΡΡŠΡΡ‚ΠΎΡΠ½ΠΈΠ΅Ρ‚ΠΎ Π½Π° индСкситС:

Анализ Π½Π° ΡΡŠΡΡ‚ΠΎΡΠ½ΠΈΠ΅Ρ‚ΠΎ Π½Π° индСкса

declare @Fragmentation float=15;
declare @MinIndexSize bigint=768;
declare @MaxIndexSize bigint=1048576;
declare @PreDescribeSize bigint=32768;
SET NOCOUNT ON
SET ARITHABORT ON
SET NUMERIC_ROUNDABORT OFF
IF OBJECT_ID('tempdb.dbo.#AllocationUnits') IS NOT NULL
DROP TABLE #AllocationUnits
CREATE TABLE #AllocationUnits (
ContainerID   BIGINT PRIMARY KEY
, ReservedPages BIGINT NOT NULL
, UsedPages     BIGINT NOT NULL
)
INSERT INTO #AllocationUnits (ContainerID, ReservedPages, UsedPages)
SELECT [container_id]
, SUM([total_pages])
, SUM([used_pages])
FROM sys.allocation_units WITH(NOLOCK)
GROUP BY [container_id]
HAVING SUM([total_pages]) BETWEEN @MinIndexSize AND @MaxIndexSize
IF OBJECT_ID('tempdb.dbo.#ExcludeList') IS NOT NULL
DROP TABLE #ExcludeList
CREATE TABLE #ExcludeList (ID INT PRIMARY KEY)
INSERT INTO #ExcludeList
SELECT [object_id]
FROM sys.objects WITH(NOLOCK)
WHERE [type] IN ('V', 'U')
AND ( [is_ms_shipped] = 1 )
IF OBJECT_ID('tempdb.dbo.#Partitions') IS NOT NULL
DROP TABLE #Partitions
SELECT [object_id]
, [index_id]
, [partition_id]
, [partition_number]
, [rows]
, [data_compression]
INTO #Partitions
FROM sys.partitions WITH(NOLOCK)
WHERE [object_id] > 255
AND [rows] > 0
AND [object_id] NOT IN (SELECT * FROM #ExcludeList)
IF OBJECT_ID('tempdb.dbo.#Indexes') IS NOT NULL
DROP TABLE #Indexes
CREATE TABLE #Indexes (
ObjectID         INT NOT NULL
, IndexID          INT NOT NULL
, IndexName        SYSNAME NULL
, PagesCount       BIGINT NOT NULL
, UnusedPagesCount BIGINT NOT NULL
, PartitionNumber  INT NOT NULL
, RowsCount        BIGINT NOT NULL
, IndexType        TINYINT NOT NULL
, IsAllowPageLocks BIT NOT NULL
, DataSpaceID      INT NOT NULL
, DataCompression  TINYINT NOT NULL
, IsUnique         BIT NOT NULL
, IsPK             BIT NOT NULL
, FillFactorValue  INT NOT NULL
, IsFiltered       BIT NOT NULL
, PRIMARY KEY (ObjectID, IndexID, PartitionNumber)
)
INSERT INTO #Indexes
SELECT ObjectID         = i.[object_id]
, IndexID          = i.index_id
, IndexName        = i.[name]
, PagesCount       = a.ReservedPages
, UnusedPagesCount = CASE WHEN ABS(a.ReservedPages - a.UsedPages) > 32 THEN a.ReservedPages - a.UsedPages ELSE 0 END
, PartitionNumber  = p.[partition_number]
, RowsCount        = ISNULL(p.[rows], 0)
, IndexType        = i.[type]
, IsAllowPageLocks = i.[allow_page_locks]
, DataSpaceID      = i.[data_space_id]
, DataCompression  = p.[data_compression]
, IsUnique         = i.[is_unique]
, IsPK             = i.[is_primary_key]
, FillFactorValue  = i.[fill_factor]
, IsFiltered       = i.[has_filter]
FROM #AllocationUnits a
JOIN #Partitions p ON a.ContainerID = p.[partition_id]
JOIN sys.indexes i WITH(NOLOCK) ON i.[object_id] = p.[object_id] AND p.[index_id] = i.[index_id] 
WHERE i.[type] IN (0, 1, 2, 5, 6)
AND i.[object_id] > 255
DECLARE @files TABLE (ID INT PRIMARY KEY)
INSERT INTO @files
SELECT DISTINCT [data_space_id]
FROM sys.database_files WITH(NOLOCK)
WHERE [state] != 0
AND [type] = 0
IF @@ROWCOUNT > 0 BEGIN
DELETE FROM i
FROM #Indexes i
LEFT JOIN sys.destination_data_spaces dds WITH(NOLOCK) ON i.DataSpaceID = dds.[partition_scheme_id] AND i.PartitionNumber = dds.[destination_id]
WHERE ISNULL(dds.[data_space_id], i.DataSpaceID) IN (SELECT * FROM @files)
END
DECLARE @DBID   INT
, @DBNAME SYSNAME
SET @DBNAME = DB_NAME()
SELECT @DBID = [database_id]
FROM sys.databases WITH(NOLOCK)
WHERE [name] = @DBNAME
IF OBJECT_ID('tempdb.dbo.#Fragmentation') IS NOT NULL
DROP TABLE #Fragmentation
CREATE TABLE #Fragmentation (
ObjectID         INT NOT NULL
, IndexID          INT NOT NULL
, PartitionNumber  INT NOT NULL
, Fragmentation    FLOAT NOT NULL
, PRIMARY KEY (ObjectID, IndexID, PartitionNumber)
)
INSERT INTO #Fragmentation (ObjectID, IndexID, PartitionNumber, Fragmentation)
SELECT i.ObjectID
, i.IndexID
, i.PartitionNumber
, r.[avg_fragmentation_in_percent]
FROM #Indexes i
CROSS APPLY sys.dm_db_index_physical_stats(@DBID, i.ObjectID, i.IndexID, i.PartitionNumber, 'LIMITED') r
WHERE i.PagesCount <= @PreDescribeSize
AND r.[index_level] = 0
AND r.[alloc_unit_type_desc] = 'IN_ROW_DATA'
AND i.IndexType IN (0, 1, 2)
IF OBJECT_ID('tempdb.dbo.#Columns') IS NOT NULL
DROP TABLE #Columns
CREATE TABLE #Columns (
ObjectID     INT NOT NULL
, ColumnID     INT NOT NULL
, ColumnName   SYSNAME NULL
, SystemTypeID TINYINT NULL
, IsSparse     BIT
, IsColumnSet  BIT
, MaxLen       INT
, PRIMARY KEY (ObjectID, ColumnID)
)
INSERT INTO #Columns
SELECT ObjectID     = [object_id]
, ColumnID     = [column_id]
, ColumnName   = [name]
, SystemTypeID = [system_type_id]
, IsSparse     = [is_sparse]
, IsColumnSet  = [is_column_set]
, MaxLen       = [max_length]
FROM sys.columns WITH(NOLOCK)
WHERE [object_id] IN (SELECT DISTINCT i.ObjectID FROM #Indexes i)
IF OBJECT_ID('tempdb.dbo.#IndexColumns') IS NOT NULL
DROP TABLE #IndexColumns
CREATE TABLE #IndexColumns (
ObjectID   INT NOT NULL
, IndexID    INT NOT NULL
, OrderID    INT NOT NULL
, ColumnID   INT NOT NULL
, IsIncluded BIT NOT NULL
, PRIMARY KEY (ObjectID, IndexID, ColumnID)
)
INSERT INTO #IndexColumns
SELECT ObjectID   = [object_id]
, IndexID    = [index_id]
, OrderID    = CASE WHEN [is_included_column] = 0 THEN [key_ordinal] ELSE [index_column_id] END
, ColumnID   = [column_id]
, IsIncluded = ISNULL([is_included_column], 0)
FROM sys.index_columns ic WITH(NOLOCK)
WHERE EXISTS(
SELECT *
FROM #Indexes i
WHERE i.ObjectID = ic.[object_id]
AND i.IndexID = ic.[index_id]
AND i.IndexType IN (1, 2)
)
IF OBJECT_ID('tempdb.dbo.#Lob') IS NOT NULL
DROP TABLE #Lob
CREATE TABLE #Lob (
ObjectID    INT NOT NULL
, IndexID     INT NOT NULL
, IsLobLegacy BIT
, IsLob       BIT
, PRIMARY KEY (ObjectID, IndexID)
)
INSERT INTO #Lob (ObjectID, IndexID, IsLobLegacy, IsLob)
SELECT c.ObjectID
, IndexID     = ISNULL(i.IndexID, 1)
, IsLobLegacy = MAX(CASE WHEN c.SystemTypeID IN (34, 35, 99) THEN 1 END)
, IsLob       = 0
FROM #Columns c
LEFT JOIN #IndexColumns i ON c.ObjectID = i.ObjectID AND c.ColumnID = i.ColumnID
WHERE c.SystemTypeID IN (34, 35, 99)
GROUP BY c.ObjectID
, i.IndexID
IF OBJECT_ID('tempdb.dbo.#Sparse') IS NOT NULL
DROP TABLE #Sparse
CREATE TABLE #Sparse (ObjectID INT PRIMARY KEY)
INSERT INTO #Sparse
SELECT DISTINCT ObjectID
FROM #Columns
WHERE IsSparse = 1
OR IsColumnSet = 1
IF OBJECT_ID('tempdb.dbo.#AggColumns') IS NOT NULL
DROP TABLE #AggColumns
CREATE TABLE #AggColumns (
ObjectID        INT NOT NULL
, IndexID         INT NOT NULL
, IndexColumns    NVARCHAR(MAX)
, IncludedColumns NVARCHAR(MAX)
, PRIMARY KEY (ObjectID, IndexID)
)
INSERT INTO #AggColumns
SELECT t.ObjectID
, t.IndexID
, IndexColumns = STUFF((
SELECT ', [' + c.ColumnName + ']'
FROM #IndexColumns i
JOIN #Columns c ON i.ObjectID = c.ObjectID AND i.ColumnID = c.ColumnID
WHERE i.ObjectID = t.ObjectID
AND i.IndexID = t.IndexID
AND i.IsIncluded = 0
ORDER BY i.OrderID
FOR XML PATH(''), TYPE).value('(./text())[1]', 'NVARCHAR(MAX)'), 1, 2, '')
, IncludedColumns = STUFF((
SELECT ', [' + c.ColumnName + ']'
FROM #IndexColumns i
JOIN #Columns c ON i.ObjectID = c.ObjectID AND i.ColumnID = c.ColumnID
WHERE i.ObjectID = t.ObjectID
AND i.IndexID = t.IndexID
AND i.IsIncluded = 1
ORDER BY i.OrderID
FOR XML PATH(''), TYPE).value('(./text())[1]', 'NVARCHAR(MAX)'), 1, 2, '')
FROM (
SELECT DISTINCT ObjectID, IndexID
FROM #Indexes
WHERE IndexType IN (1, 2)
) t
SELECT i.ObjectID
, i.IndexID
, i.IndexName
, ObjectName       = o.[name]
, SchemaName       = s.[name]
, i.PagesCount
, i.UnusedPagesCount
, i.PartitionNumber
, i.RowsCount
, i.IndexType
, i.IsAllowPageLocks
, u.TotalWrites
, u.TotalReads
, u.TotalSeeks
, u.TotalScans
, u.TotalLookups
, u.LastUsage
, i.DataCompression
, f.Fragmentation
, IndexStats       = STATS_DATE(i.ObjectID, i.IndexID)
, IsLobLegacy      = ISNULL(lob.IsLobLegacy, 0)
, IsLob            = ISNULL(lob.IsLob, 0)
, IsSparse         = CAST(CASE WHEN p.ObjectID IS NULL THEN 0 ELSE 1 END AS BIT)
, IsPartitioned    = CAST(CASE WHEN dds.[data_space_id] IS NOT NULL THEN 1 ELSE 0 END AS BIT)
, FileGroupName    = fg.[name]
, i.IsUnique
, i.IsPK
, i.FillFactorValue
, i.IsFiltered
, a.IndexColumns
, a.IncludedColumns
FROM #Indexes i
JOIN sys.objects o WITH(NOLOCK) ON o.[object_id] = i.ObjectID
JOIN sys.schemas s WITH(NOLOCK) ON s.[schema_id] = o.[schema_id]
LEFT JOIN #AggColumns a ON a.ObjectID = i.ObjectID AND a.IndexID = i.IndexID
LEFT JOIN #Sparse p ON p.ObjectID = i.ObjectID
LEFT JOIN #Fragmentation f ON f.ObjectID = i.ObjectID AND f.IndexID = i.IndexID AND f.PartitionNumber = i.PartitionNumber
LEFT JOIN (
SELECT ObjectID      = [object_id]
, IndexID       = [index_id]
, TotalWrites   = NULLIF([user_updates], 0)
, TotalReads    = NULLIF([user_seeks] + [user_scans] + [user_lookups], 0)
, TotalSeeks    = NULLIF([user_seeks], 0)
, TotalScans    = NULLIF([user_scans], 0)
, TotalLookups  = NULLIF([user_lookups], 0)
, LastUsage     = (
SELECT MAX(dt)
FROM (
VALUES ([last_user_seek])
, ([last_user_scan])
, ([last_user_lookup])
, ([last_user_update])
) t(dt)
)
FROM sys.dm_db_index_usage_stats WITH(NOLOCK)
WHERE [database_id] = @DBID
) u ON i.ObjectID = u.ObjectID AND i.IndexID = u.IndexID
LEFT JOIN #Lob lob ON lob.ObjectID = i.ObjectID AND lob.IndexID = i.IndexID
LEFT JOIN sys.destination_data_spaces dds WITH(NOLOCK) ON i.DataSpaceID = dds.[partition_scheme_id] AND i.PartitionNumber = dds.[destination_id]
JOIN sys.filegroups fg WITH(NOLOCK) ON ISNULL(dds.[data_space_id], i.DataSpaceID) = fg.[data_space_id] 
WHERE o.[type] IN ('V', 'U')
AND (
f.Fragmentation >= @Fragmentation
OR
i.PagesCount > @PreDescribeSize
OR
i.IndexType IN (5, 6)
)

ΠšΠ°ΠΊΡ‚ΠΎ сС Π²ΠΈΠΆΠ΄Π° ΠΎΡ‚ самитС заявки, Π²Ρ€Π΅ΠΌΠ΅Π½Π½ΠΈΡ‚Π΅ Ρ‚Π°Π±Π»ΠΈΡ†ΠΈ сС ΠΈΠ·ΠΏΠΎΠ»Π·Π²Π°Ρ‚ доста чСсто. Π’ΠΎΠ²Π° сС ΠΏΡ€Π°Π²ΠΈ, Π·Π° Π΄Π° няма ΠΏΠΎΠ²Ρ‚ΠΎΡ€Π½ΠΈ ΠΊΠΎΠΌΠΏΠΈΠ»Π°Ρ†ΠΈΠΈ ΠΈ Π² случай Π½Π° голяма схСма ΠΏΠ»Π°Π½ΡŠΡ‚ ΠΌΠΎΠΆΠ΅ Π΄Π° сС Π³Π΅Π½Π΅Ρ€ΠΈΡ€Π° ΠΏΠ°Ρ€Π°Π»Π΅Π»Π½ΠΎ ΠΏΡ€ΠΈ вмъкванС Π½Π° Π΄Π°Π½Π½ΠΈ, Ρ‚ΡŠΠΉ ΠΊΠ°Ρ‚ΠΎ Π²ΠΌΡŠΠΊΠ²Π°Π½Π΅Ρ‚ΠΎ Π½Π° ΠΏΡ€ΠΎΠΌΠ΅Π½Π»ΠΈΠ²ΠΈ Π½Π° Ρ‚Π°Π±Π»ΠΈΡ†Π° Π΅ възмоТно само Π² Π΅Π΄Π½Π° нишка.

Π‘Π»Π΅Π΄ изпълнСниС Π½Π° горния скрипт Ρ‰Π΅ сС появи ΠΏΡ€ΠΎΠ·ΠΎΡ€Π΅Ρ† с индСксна Ρ‚Π°Π±Π»ΠΈΡ†Π°:

ΠŸΡ€Π΅Π³Π»Π΅Π΄ Π½Π° бСзплатния инструмСнт SQLIndexManager

Π’ΡƒΠΊ ΠΌΠΎΠΆΠ΅Ρ‚Π΅ Π΄Π° ΠΏΠΎΠΊΠ°ΠΆΠ΅Ρ‚Π΅ ΠΈ Π΄Ρ€ΡƒΠ³Π° ΠΏΠΎΠ΄Ρ€ΠΎΠ±Π½Π° информация, ΠΊΠ°Ρ‚ΠΎ Π½Π°ΠΏΡ€ΠΈΠΌΠ΅Ρ€:

  1. Π±Π°Π·Π° Π΄Π°Π½Π½ΠΈ
  2. Π±Ρ€ΠΎΠΉ сСкции
  3. Π΄Π°Ρ‚Π° ΠΈ час Π½Π° послСдното ΠΎΠ±Π°ΠΆΠ΄Π°Π½Π΅
  4. компрСсия
  5. Ρ„Π°ΠΉΠ»ΠΎΠ²Π° Π³Ρ€ΡƒΠΏΠ°

ΠΈ Ρ‚. Π³.
Π‘Π°ΠΌΠΈΡ‚Π΅ високоговоритСли ΠΌΠΎΠ³Π°Ρ‚ Π΄Π° Π±ΡŠΠ΄Π°Ρ‚ пСрсонализирани:

ΠŸΡ€Π΅Π³Π»Π΅Π΄ Π½Π° бСзплатния инструмСнт SQLIndexManager

Π’ ΠΊΠ»Π΅Ρ‚ΠΊΠΈΡ‚Π΅ Π½Π° ΠΊΠΎΠ»ΠΎΠ½Π°Ρ‚Π° Fix ΠΌΠΎΠΆΠ΅Ρ‚Π΅ Π΄Π° ΠΈΠ·Π±Π΅Ρ€Π΅Ρ‚Π΅ ΠΊΠ°ΠΊΠ²ΠΎ дСйствиС Π΄Π° сС ΠΈΠ·Π²ΡŠΡ€ΡˆΠΈ ΠΏΠΎ Π²Ρ€Π΅ΠΌΠ΅ Π½Π° оптимизацията. Π‘ΡŠΡ‰ΠΎ Ρ‚Π°ΠΊΠ°, ΠΊΠΎΠ³Π°Ρ‚ΠΎ сканиранСто Π·Π°Π²ΡŠΡ€ΡˆΠΈ, сС ΠΈΠ·Π±ΠΈΡ€Π° дСйствиС ΠΏΠΎ ΠΏΠΎΠ΄Ρ€Π°Π·Π±ΠΈΡ€Π°Π½Π΅ въз основа Π½Π° ΠΈΠ·Π±Ρ€Π°Π½ΠΈΡ‚Π΅ настройки:

ΠŸΡ€Π΅Π³Π»Π΅Π΄ Π½Π° бСзплатния инструмСнт SQLIndexManager

Врябва Π΄Π° ΠΈΠ·Π±Π΅Ρ€Π΅Ρ‚Π΅ ΠΆΠ΅Π»Π°Π½ΠΈΡ‚Π΅ индСкси Π·Π° ΠΎΠ±Ρ€Π°Π±ΠΎΡ‚ΠΊΠ°.

Π‘ ΠΏΠΎΠΌΠΎΡ‰Ρ‚Π° Π½Π° Π³Π»Π°Π²Π½ΠΎΡ‚ΠΎ мСню ΠΌΠΎΠΆΠ΅Ρ‚Π΅ Π΄Π° Π·Π°ΠΏΠ°Π·ΠΈΡ‚Π΅ скрипта (ΡΡŠΡ‰ΠΈΡΡ‚ Π±ΡƒΡ‚ΠΎΠ½ стартира самия процСс Π½Π° ΠΎΠΏΡ‚ΠΈΠΌΠΈΠ·ΠΈΡ€Π°Π½Π΅ Π½Π° индСкса):

ΠŸΡ€Π΅Π³Π»Π΅Π΄ Π½Π° бСзплатния инструмСнт SQLIndexManager

ΠΈ Π·Π°ΠΏΠ°Π·Π΅Ρ‚Π΅ Ρ‚Π°Π±Π»ΠΈΡ†Π°Ρ‚Π° Π² Ρ€Π°Π·Π»ΠΈΡ‡Π½ΠΈ Ρ„ΠΎΡ€ΠΌΠ°Ρ‚ΠΈ (ΡΡŠΡ‰ΠΈΡΡ‚ Π±ΡƒΡ‚ΠΎΠ½ Π²ΠΈ позволява Π΄Π° ΠΎΡ‚Π²ΠΎΡ€ΠΈΡ‚Π΅ ΠΏΠΎΠ΄Ρ€ΠΎΠ±Π½ΠΈ настройки Π·Π° Π°Π½Π°Π»ΠΈΠ·ΠΈΡ€Π°Π½Π΅ ΠΈ ΠΎΠΏΡ‚ΠΈΠΌΠΈΠ·ΠΈΡ€Π°Π½Π΅ Π½Π° индСкси):

ΠŸΡ€Π΅Π³Π»Π΅Π΄ Π½Π° бСзплатния инструмСнт SQLIndexManager

ΠœΠΎΠΆΠ΅Ρ‚Π΅ ΡΡŠΡ‰ΠΎ Ρ‚Π°ΠΊΠ° Π΄Π° Π°ΠΊΡ‚ΡƒΠ°Π»ΠΈΠ·ΠΈΡ€Π°Ρ‚Π΅ информацията, ΠΊΠ°Ρ‚ΠΎ Ρ‰Ρ€Π°ΠΊΠ½Π΅Ρ‚Π΅ Π²ΡŠΡ€Ρ…Ρƒ трСтия Π±ΡƒΡ‚ΠΎΠ½ вляво Π² Π³Π»Π°Π²Π½ΠΎΡ‚ΠΎ мСню Π΄ΠΎ Π»ΡƒΠΏΠ°Ρ‚Π°.

Π‘ΡƒΡ‚ΠΎΠ½ΡŠΡ‚ с Π»ΡƒΠΏΠ° Π²ΠΈ позволява Π΄Π° ΠΈΠ·Π±Π΅Ρ€Π΅Ρ‚Π΅ ΠΆΠ΅Π»Π°Π½ΠΈΡ‚Π΅ Π±Π°Π·ΠΈ Π΄Π°Π½Π½ΠΈ Π·Π° Ρ€Π°Π·Π³Π»Π΅ΠΆΠ΄Π°Π½Π΅.

Π’ ΠΌΠΎΠΌΠ΅Π½Ρ‚Π° няма цялостна систСма Π·Π° ΠΏΠΎΠΌΠΎΡ‰. Π‘Π»Π΅Π΄ΠΎΠ²Π°Ρ‚Π΅Π»Π½ΠΎ, натисканСто Π½Π° Π±ΡƒΡ‚ΠΎΠ½Π° "?" просто Ρ‰Π΅ ΠΏΡ€Π΅Π΄ΠΈΠ·Π²ΠΈΠΊΠ° появата Π½Π° ΠΌΠΎΠ΄Π°Π»Π΅Π½ ΠΏΡ€ΠΎΠ·ΠΎΡ€Π΅Ρ†, ΡΡŠΠ΄ΡŠΡ€ΠΆΠ°Ρ‰ основна информация Π·Π° софтуСрния ΠΏΡ€ΠΎΠ΄ΡƒΠΊΡ‚:

ΠŸΡ€Π΅Π³Π»Π΅Π΄ Π½Π° бСзплатния инструмСнт SQLIndexManager

Π’ допълнСниС към всичко описано ΠΏΠΎ-Π³ΠΎΡ€Π΅, Π³Π»Π°Π²Π½ΠΎΡ‚ΠΎ мСню ΠΈΠΌΠ° Π»Π΅Π½Ρ‚Π° Π·Π° Ρ‚ΡŠΡ€ΡΠ΅Π½Π΅:

ΠŸΡ€Π΅Π³Π»Π΅Π΄ Π½Π° бСзплатния инструмСнт SQLIndexManager

ΠšΠΎΠ³Π°Ρ‚ΠΎ стартиратС процСса Π½Π° ΠΎΠΏΡ‚ΠΈΠΌΠΈΠ·ΠΈΡ€Π°Π½Π΅ Π½Π° индСкса:

ΠŸΡ€Π΅Π³Π»Π΅Π΄ Π½Π° бСзплатния инструмСнт SQLIndexManager

ΠœΠΎΠΆΠ΅Ρ‚Π΅ ΡΡŠΡ‰ΠΎ Ρ‚Π°ΠΊΠ° Π΄Π° Π²ΠΈΠ΄ΠΈΡ‚Π΅ Ρ€Π΅Π³ΠΈΡΡ‚ΡŠΡ€ Π½Π° ΠΈΠ·Π²ΡŠΡ€ΡˆΠ΅Π½ΠΈΡ‚Π΅ дСйствия Π² Π΄ΠΎΠ»Π½Π°Ρ‚Π° част Π½Π° ΠΏΡ€ΠΎΠ·ΠΎΡ€Π΅Ρ†Π°:

ΠŸΡ€Π΅Π³Π»Π΅Π΄ Π½Π° бСзплатния инструмСнт SQLIndexManager

Π’ ΠΏΡ€ΠΎΠ·ΠΎΡ€Π΅Ρ†Π° с ΠΏΠΎΠ΄Ρ€ΠΎΠ±Π½ΠΈ настройки Π·Π° Π°Π½Π°Π»ΠΈΠ· Π½Π° индСкса ΠΈ оптимизация ΠΌΠΎΠΆΠ΅Ρ‚Π΅ Π΄Π° ΠΊΠΎΠ½Ρ„ΠΈΠ³ΡƒΡ€ΠΈΡ€Π°Ρ‚Π΅ ΠΏΠΎ-Ρ„ΠΈΠ½ΠΈ ΠΎΠΏΡ†ΠΈΠΈ:

ΠŸΡ€Π΅Π³Π»Π΅Π΄ Π½Π° бСзплатния инструмСнт SQLIndexManager

Заявки Π·Π° кандидатстванС:

  1. правят възмоТно сСлСктивно Π°ΠΊΡ‚ΡƒΠ°Π»ΠΈΠ·ΠΈΡ€Π°Π½Π΅ Π½Π° статистика Π½Π΅ само Π·Π° индСкси, Π½ΠΎ ΠΈ ΠΏΠΎ Ρ€Π°Π·Π»ΠΈΡ‡Π½ΠΈ Π½Π°Ρ‡ΠΈΠ½ΠΈ (напълно Π°ΠΊΡ‚ΡƒΠ°Π»ΠΈΠ·ΠΈΡ€Π°Π½Π΅ ΠΈΠ»ΠΈ частично)
  2. Π΄Π°Π²Π°Ρ‚ Π²ΡŠΠ·ΠΌΠΎΠΆΠ½ΠΎΡΡ‚ Π½Π΅ само Π΄Π° ΠΈΠ·Π±Π΅Ρ€Π΅Ρ‚Π΅ Π±Π°Π·Π° Π΄Π°Π½Π½ΠΈ, Π½ΠΎ ΠΈ Ρ€Π°Π·Π»ΠΈΡ‡Π½ΠΈ ΡΡŠΡ€Π²ΡŠΡ€ΠΈ (Ρ‚ΠΎΠ²Π° Π΅ ΠΌΠ½ΠΎΠ³ΠΎ ΡƒΠ΄ΠΎΠ±Π½ΠΎ, ΠΊΠΎΠ³Π°Ρ‚ΠΎ ΠΈΠΌΠ° ΠΌΠ½ΠΎΠ³ΠΎ СкзСмпляри Π½Π° MS SQL Server)
  3. Π—Π° ΠΏΠΎ-голяма Π³ΡŠΠ²ΠΊΠ°Π²ΠΎΡΡ‚ ΠΏΡ€ΠΈ ΠΈΠ·ΠΏΠΎΠ»Π·Π²Π°Π½Π΅ сС ΠΏΡ€Π΅ΠΏΠΎΡ€ΡŠΡ‡Π²Π° Π΄Π° ΠΎΠ±Π²ΠΈΠ΅Ρ‚Π΅ ΠΊΠΎΠΌΠ°Π½Π΄ΠΈΡ‚Π΅ Π² Π±ΠΈΠ±Π»ΠΈΠΎΡ‚Π΅ΠΊΠΈ ΠΈ Π΄Π° Π³ΠΈ ΠΈΠ·Π²Π΅Π΄Π΅Ρ‚Π΅ към ΠΊΠΎΠΌΠ°Π½Π΄ΠΈ Π½Π° PowerShell, ΠΊΠ°ΠΊΡ‚ΠΎ Π΅ Π½Π°ΠΏΡ€Π°Π²Π΅Π½ΠΎ Π½Π°ΠΏΡ€ΠΈΠΌΠ΅Ρ€ Ρ‚ΡƒΠΊ:
  4. dbatools.io/commands
  5. правят възмоТно Π·Π°ΠΏΠ°Π·Π²Π°Π½Π΅Ρ‚ΠΎ ΠΈ промяната Π½Π° пСрсонални настройки ΠΊΠ°ΠΊΡ‚ΠΎ Π·Π° цялото ΠΏΡ€ΠΈΠ»ΠΎΠΆΠ΅Π½ΠΈΠ΅, Ρ‚Π°ΠΊΠ° ΠΈ, Π°ΠΊΠΎ Π΅ Π½Π΅ΠΎΠ±Ρ…ΠΎΠ΄ΠΈΠΌΠΎ, Π·Π° всяко ΠΊΠΎΠΏΠΈΠ΅ Π½Π° MS SQL Server ΠΈ всяка Π±Π°Π·Π° Π΄Π°Π½Π½ΠΈ
  6. ΠžΡ‚ Ρ‚ΠΎΡ‡ΠΊΠΈ 2 ΠΈ 4 слСдва, Ρ‡Π΅ искатС Π΄Π° ΡΡŠΠ·Π΄Π°Π²Π°Ρ‚Π΅ Π³Ρ€ΡƒΠΏΠΈ ΠΏΠΎ Π±Π°Π·ΠΈ Π΄Π°Π½Π½ΠΈ ΠΈ Π³Ρ€ΡƒΠΏΠΈ ΠΏΠΎ СкзСмпляри Π½Π° MS SQL Server, Π·Π° ΠΊΠΎΠΈΡ‚ΠΎ настройкитС са Π΅Π΄Π½Π°ΠΊΠ²ΠΈ
  7. Ρ‚ΡŠΡ€ΡΠ΅Π½Π΅ Π½Π° Π΄ΡƒΠ±Π»ΠΈΡ€Π°Ρ‰ΠΈ сС индСкси (пълни ΠΈ нСпълни, ΠΊΠΎΠΈΡ‚ΠΎ са ΠΈΠ»ΠΈ ΠΌΠ°Π»ΠΊΠΎ Ρ€Π°Π·Π»ΠΈΡ‡Π½ΠΈ, ΠΈΠ»ΠΈ сС Ρ€Π°Π·Π»ΠΈΡ‡Π°Π²Π°Ρ‚ само във Π²ΠΊΠ»ΡŽΡ‡Π΅Π½ΠΈΡ‚Π΅ ΠΊΠΎΠ»ΠΎΠ½ΠΈ)
  8. Въй ΠΊΠ°Ρ‚ΠΎ SQLIndexManager сС ΠΈΠ·ΠΏΠΎΠ»Π·Π²Π° само Π·Π° MS SQL Server DBMS, Π΅ Π½Π΅ΠΎΠ±Ρ…ΠΎΠ΄ΠΈΠΌΠΎ Ρ‚ΠΎΠ²Π° Π΄Π° сС ΠΎΡ‚Ρ€Π°Π·ΠΈ Π² ΠΈΠΌΠ΅Ρ‚ΠΎ, Π½Π°ΠΏΡ€ΠΈΠΌΠ΅Ρ€, ΠΊΠ°ΠΊΡ‚ΠΎ слСдва: SQLIndexManager Π·Π° MS SQL Server
  9. ΠŸΡ€Π΅ΠΌΠ΅ΡΡ‚Π΅Ρ‚Π΅ всички Π½Π΅-GUI части Π½Π° ΠΏΡ€ΠΈΠ»ΠΎΠΆΠ΅Π½ΠΈΠ΅Ρ‚ΠΎ Π² ΠΎΡ‚Π΄Π΅Π»Π½ΠΈ ΠΌΠΎΠ΄ΡƒΠ»ΠΈ ΠΈ Π³ΠΈ ΠΏΡ€Π΅Π½Π°ΠΏΠΈΡˆΠ΅Ρ‚Π΅ Π² .NET Core 2.1

Към ΠΌΠΎΠΌΠ΅Π½Ρ‚Π° Π½Π° писанС, Ρ‚ΠΎΡ‡ΠΊΠ° 6 ΠΎΡ‚ ТСланията сС Ρ€Π°Π·Ρ€Π°Π±ΠΎΡ‚Π²Π° Π°ΠΊΡ‚ΠΈΠ²Π½ΠΎ ΠΈ Π²Π΅Ρ‡Π΅ ΠΈΠΌΠ° ΠΏΠΎΠ΄Π΄Ρ€ΡŠΠΆΠΊΠ° ΠΏΠΎΠ΄ Ρ„ΠΎΡ€ΠΌΠ°Ρ‚Π° Π½Π° Ρ‚ΡŠΡ€ΡΠ΅Π½Π΅ Π½Π° пълни ΠΈ ΠΏΠΎΠ΄ΠΎΠ±Π½ΠΈ Π΄ΡƒΠ±Π»ΠΈΠΊΠ°Ρ‚ΠΈ:

ΠŸΡ€Π΅Π³Π»Π΅Π΄ Π½Π° бСзплатния инструмСнт SQLIndexManager

ΠΈΠ·Ρ‚ΠΎΡ‡Π½ΠΈΡ†ΠΈ

Π˜Π·Ρ‚ΠΎΡ‡Π½ΠΈΠΊ: www.habr.com

ДобавянС Π½Π° Π½ΠΎΠ² ΠΊΠΎΠΌΠ΅Π½Ρ‚Π°Ρ€