ืกืงื™ืจื” ืฉืœ ื”ื›ืœื™ ื”ื—ื™ื ืžื™ SQLIndexManager

ื›ืคื™ ืฉืืชื” ื™ื•ื“ืข, ืื™ื ื“ืงืกื™ื ืžืžืœืื™ื ืชืคืงื™ื“ ื—ืฉื•ื‘ ื‘-DBMS, ื•ืžืกืคืงื™ื ื—ื™ืคื•ืฉ ืžื”ื™ืจ ืœืจืฉื•ืžื•ืช ื”ื ื“ืจืฉื•ืช. ืœื›ืŸ ื–ื” ื›ืœ ื›ืš ื—ืฉื•ื‘ ืœืชืช ืœื”ื ืฉื™ืจื•ืช ื‘ื–ืžืŸ. ืœื ืžืขื˜ ื—ื•ืžืจ ื ื›ืชื‘ ืขืœ ื ื™ืชื•ื— ื•ืื•ืคื˜ื™ืžื™ื–ืฆื™ื”, ื›ื•ืœืœ ื‘ืื™ื ื˜ืจื ื˜. ืœื“ื•ื’ืžื”, ื ื•ืฉื ื–ื” ื ื‘ื“ืง ืœืื—ืจื•ื ื” ื‘ ืคืจืกื•ื ื–ื”.

ื™ืฉ ื”ืจื‘ื” ืคืชืจื•ื ื•ืช ื‘ืชืฉืœื•ื ื•ื—ื™ื ืžื™ื™ื ืœื›ืš. ืœื“ื•ื’ืžื”, ื™ืฉ ืžื•ื›ืŸ ื”ื—ืœื˜ื”, ืžื‘ื•ืกืก ืขืœ ืฉื™ื˜ืช ืื•ืคื˜ื™ืžื™ื–ืฆื™ื” ืฉืœ ืื™ื ื“ืงืก ืื“ืคื˜ื™ื‘ื™.

ืœืื—ืจ ืžื›ืŸ, ื‘ื•ืื• ื ืกืชื›ืœ ืขืœ ื›ืœื™ ื”ืฉื™ืจื•ืช ื”ื—ื™ื ืžื™ SQLIndexManager, ื—ื•ื‘ืจ ืขืœ ื™ื“ื™ ืืœื ื“ื ื˜ื•ืŸ.

ื”ื”ื‘ื“ืœ ื”ื˜ื›ื ื™ ื”ืขื™ืงืจื™ ื‘ื™ืŸ SQLIndexManager ืœืžืกืคืจ ืื ืœื•ื’ื™ื ืื—ืจื™ื ื ื™ืชืŸ ืขืœ ื™ื“ื™ ื”ืžื—ื‘ืจ ืขืฆืžื• ื›ืืŸ ะธ ื›ืืŸ.

ื‘ืžืืžืจ ื–ื”, ื ืกืงื•ืจ ืืช ื”ืคืจื•ื™ืงื˜ ื•ืืช ื”ื™ื›ื•ืœื•ืช ื”ืชืคืขื•ืœื™ื•ืช ืฉืœ ืคืชืจื•ืŸ ืชื•ื›ื ื” ื–ื”.

ื“ื™ื•ืŸ ืขืœ ื›ืœื™ ื”ืฉื™ืจื•ืช ื”ื–ื” ื›ืืŸ.
ืขื ื”ื–ืžืŸ, ืจื•ื‘ ื”ื”ืขืจื•ืช ื•ื”ื‘ืื’ื™ื ืชื•ืงื ื•.

ืื– ื‘ื•ืื• ื ืขื‘ื•ืจ ื›ืขืช ืœื›ืœื™ ื”ืฉื™ืจื•ืช SQLIndexManager ืขืฆืžื•.

ื”ืืคืœื™ืงืฆื™ื” ื›ืชื•ื‘ื” ื‘-C# .NET Framework 4.5 ื‘-Visual Studio 2017 ื•ืžืฉืชืžืฉืช ื‘-DevExpress ืขื‘ื•ืจ ื˜ืคืกื™ื:

ืกืงื™ืจื” ืฉืœ ื”ื›ืœื™ ื”ื—ื™ื ืžื™ SQLIndexManager

ื•ื ืจืื” ื›ืš:

ืกืงื™ืจื” ืฉืœ ื”ื›ืœื™ ื”ื—ื™ื ืžื™ SQLIndexManager

ื›ืœ ื”ื‘ืงืฉื•ืช ื ื•ืฆืจื•ืช ื‘ืงื‘ืฆื™ื ื”ื‘ืื™ื:

  1. ืžื“ื“
  2. ืฉืืœื”
  3. QueryEngine
  4. ServerInfo

ืกืงื™ืจื” ืฉืœ ื”ื›ืœื™ ื”ื—ื™ื ืžื™ SQLIndexManager

ื‘ืขืช ื”ืชื—ื‘ืจื•ืช ืœืžืกื“ ื ืชื•ื ื™ื ื•ืฉืœื™ื—ืช ืฉืื™ืœืชื•ืช ืœ-DBMS, ื”ื™ื™ืฉื•ื ื ื—ืชื ื‘ืื•ืคืŸ ื”ื‘ื:

ApplicationName=โ€SQLIndexManagerโ€

ื›ืืฉืจ ืืชื” ืžืคืขื™ืœ ืืช ื”ื™ื™ืฉื•ื, ื™ื™ืคืชื— ื—ืœื•ืŸ ืžื•ื“ืืœื™ ืœื”ื•ืกืคืช ื—ื™ื‘ื•ืจ:
ืกืงื™ืจื” ืฉืœ ื”ื›ืœื™ ื”ื—ื™ื ืžื™ SQLIndexManager

ื›ืืŸ, ื˜ืขื™ื ืช ืจืฉื™ืžื” ืžืœืื” ืฉืœ ื›ืœ ืžื•ืคืขื™ MS SQL Server ื”ื ื’ื™ืฉื™ื ื‘ืจืฉืชื•ืช ืžืงื•ืžื™ื•ืช ืขื“ื™ื™ืŸ ืœื ืขื•ื‘ื“ืช.

ืืชื” ื™ื›ื•ืœ ื’ื ืœื”ื•ืกื™ืฃ ื—ื™ื‘ื•ืจ ื‘ืืžืฆืขื•ืช ื”ื›ืคืชื•ืจ ื”ืฉืžืืœื™ ื‘ื™ื•ืชืจ ื‘ืชืคืจื™ื˜ ื”ืจืืฉื™:

ืกืงื™ืจื” ืฉืœ ื”ื›ืœื™ ื”ื—ื™ื ืžื™ SQLIndexManager

ืœืื—ืจ ืžื›ืŸ, ื”ืฉืื™ืœืชื•ืช ื”ื‘ืื•ืช ืœ-DBMS ื™ื•ืคืขืœื•:

  1. ื”ืฉื’ืช ืžื™ื“ืข ืขืœ ื”-DBMS
    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. ืื ืื™ืŸ ื–ื›ื•ื™ื•ืช ื›ืืœื”, ืื– ืคื—ื•ืช ื ืชื•ื ื™ื ืคืฉื•ื˜ ืžื•ื—ื–ืจื™ื ื›ื“ื™ ืœื ืœื”ืื˜ ืืช ื”ื‘ืงืฉื”.

ื›ืืŸ ืืชื” ืฆืจื™ืš ืœื‘ื—ื•ืจ ืืช ืžืกื“ื™ ื”ื ืชื•ื ื™ื ื”ืžืขื ื™ื™ื ื™ื ื•ืœืœื—ื•ืฅ ืขืœ ื›ืคืชื•ืจ "ืื™ืฉื•ืจ".

ืœืื—ืจ ืžื›ืŸ, ื”ืกืงืจื™ืคื˜ ื”ื‘ื ื™ื‘ื•ืฆืข ืขื‘ื•ืจ ื›ืœ ืžืกื“ ื ืชื•ื ื™ื ืฉื ื‘ื—ืจ ื›ื“ื™ ืœื ืชื— ืืช ืžืฆื‘ ื”ืื™ื ื“ืงืกื™ื:

ื ื™ืชื•ื— ืžืฆื‘ ืื™ื ื“ืงืก

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

ื”ื•ืกืคืช ืชื’ื•ื‘ื”