Ndemanga za chida chaulere cha SQLIndexManager

Monga mukudziwira, ma index amatenga gawo lofunikira mu DBMS, kupereka kusaka mwachangu ku zolemba zofunika. Ichi ndichifukwa chake ndikofunikira kwambiri kuti muwatumikire munthawi yake. Zambiri zalembedwa za kusanthula ndi kukhathamiritsa, kuphatikiza pa intaneti. Mwachitsanzo, mutuwu udawunikiridwa posachedwa mu chofalitsidwa ichi.

Pali zambiri zolipira komanso zaulere zothetsera izi. Mwachitsanzo, pali okonzeka zopangidwa chisankho, kutengera njira ya adaptive index optimization.

Kenako, tiyeni tiwone zaulere SQLIndexManager, olembedwa ndi AlanDenton.

Kusiyana kwakukulu kwaukadaulo pakati pa SQLIndexManager ndi ma analogi ena angapo amaperekedwa ndi wolemba mwiniwake apa ΠΈ apa.

M'nkhaniyi, tiyang'ana kunja kwa pulojekitiyi ndi mphamvu zogwiritsira ntchito pulogalamuyo.

Kukambirana zothandiza izi apa.
M'kupita kwa nthawi, ndemanga zambiri ndi zolakwika zinakonzedwa.

Chifukwa chake, tiyeni tsopano tipitirire ku SQLIndexManager chida chokha.

Pulogalamuyi idalembedwa mu C# .NET Framework 4.5 mu Visual Studio 2017 ndipo imagwiritsa ntchito DevExpress pamafomu:

Ndemanga za chida chaulere cha SQLIndexManager

ndipo zikuwoneka motere:

Ndemanga za chida chaulere cha SQLIndexManager

Zopempha zonse zimapangidwa m'mafayilo otsatirawa:

  1. Index
  2. Kufufuza
  3. QueryEngine
  4. ServerInfo

Ndemanga za chida chaulere cha SQLIndexManager

Mukalumikiza ku database ndikutumiza mafunso ku DBMS, ntchitoyo imasainidwa motere:

ApplicationName=”SQLIndexManager”

Mukakhazikitsa pulogalamuyi, zenera la modal lidzatsegulidwa kuti muwonjezere kulumikizana:
Ndemanga za chida chaulere cha SQLIndexManager

Apa, kukweza mndandanda wathunthu wa zochitika zonse za MS SQL Server zopezeka pamanetiweki akumaloko sikugwirabe ntchito.

Mutha kuwonjezeranso kulumikizana pogwiritsa ntchito batani lakumanzere pa menyu yayikulu:

Ndemanga za chida chaulere cha SQLIndexManager

Kenako, mafunso otsatirawa ku DBMS adzakhazikitsidwa:

  1. Kupeza zambiri za DBMS
    SELECT ProductLevel  = SERVERPROPERTY('ProductLevel')
         , Edition       = SERVERPROPERTY('Edition')
         , ServerVersion = SERVERPROPERTY('ProductVersion')
         , IsSysAdmin    = CAST(IS_SRVROLEMEMBER('sysadmin') AS BIT)
    

  2. Kupeza mndandanda wazomwe zilipo ndi katundu wawo wachidule
    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
    

Mukamaliza kulemba zomwe zili pamwambapa, zenera lidzawoneka lomwe lili ndi chidziwitso chachidule cha nkhokwe zamtundu wosankhidwa wa MS SQL Server:

Ndemanga za chida chaulere cha SQLIndexManager

Ndikoyenera kudziwa kuti zambiri zowonjezera zimawonetsedwa kutengera ufulu. Ngati alipo alireza, ndiye mutha kusankha deta kuchokera pazowonera sys.master_files. Ngati palibe ufulu wotero, ndiye kuti deta yocheperako imangobwezedwa kuti musachepetse pempho.

Apa muyenera kusankha Nawonso achichepere chidwi ndi kumadula "Chabwino" batani.

Chotsatira, script yotsatirayi idzaperekedwa pa database iliyonse yosankhidwa kuti mufufuze momwe ma index alili:

Kusanthula mbiri ya index

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)
)

Monga momwe zikuwonekera kuchokera ku mafunso okha, matebulo osakhalitsa amagwiritsidwa ntchito nthawi zambiri. Izi zimachitidwa kuti pasakhale kubwezeredwa, ndipo pakakhala chiwembu chachikulu, dongosololi likhoza kupangidwa mofanana poika deta, popeza kuyika zosintha za tebulo n'zotheka kokha mu ulusi umodzi.

Mukamaliza kulemba pamwambapa, zenera lomwe lili ndi tebulo la index lidzawonekera:

Ndemanga za chida chaulere cha SQLIndexManager

Mutha kuwonetsanso zambiri zatsatanetsatane apa, monga:

  1. database
  2. chiwerengero cha zigawo
  3. tsiku ndi nthawi yomaliza kuyimba
  4. kukanikiza
  5. filegroup

i. d.
Okamba okha amatha kusinthidwa mwamakonda:

Ndemanga za chida chaulere cha SQLIndexManager

M'maselo a Fix column, mutha kusankha zomwe zidzachitike pakukhathamiritsa. Komanso, sikaniyo ikatha, chinthu chosasinthika chimasankhidwa kutengera zomwe mwasankha:

Ndemanga za chida chaulere cha SQLIndexManager

Muyenera kusankha ma index omwe mukufuna kuti mukonze.

Pogwiritsa ntchito menyu yayikulu, mutha kusunga script (batani lomwelo limayambitsa ndondomeko yokhathamiritsa yokha):

Ndemanga za chida chaulere cha SQLIndexManager

ndikusunga tebulo m'mawonekedwe osiyanasiyana (batani lomwelo limakupatsani mwayi wotsegula makonda kuti muwunike ndikuwongolera ma index):

Ndemanga za chida chaulere cha SQLIndexManager

Mukhozanso kusintha zambiri podina batani lachitatu kumanzere mu mndandanda waukulu pafupi ndi galasi lokulitsa.

Batani lokhala ndi galasi lokulitsa limakupatsani mwayi wosankha nkhokwe zomwe mukufuna kuziganizira.

Panopa palibe njira yothandizira yokwanira. Chifukwa chake, kukanikiza batani "?" zidzangopangitsa kuti zenera la modal liwonekere lomwe lili ndi chidziwitso chofunikira chokhudza pulogalamuyo:

Ndemanga za chida chaulere cha SQLIndexManager

Kuphatikiza pa zonse zomwe zafotokozedwa pamwambapa, menyu yayikulu ili ndi bar yofufuzira:

Ndemanga za chida chaulere cha SQLIndexManager

Mukayamba ndondomeko yowonjezera index:

Ndemanga za chida chaulere cha SQLIndexManager

Mutha kuwonanso chipika cha zomwe zachitika pansi pawindo:

Ndemanga za chida chaulere cha SQLIndexManager

Pazenera lazatsatanetsatane la kusanthula kwa index ndi kukhathamiritsa, mutha kukonza zosankha zosawoneka bwino:

Ndemanga za chida chaulere cha SQLIndexManager

Zofunsira:

  1. pangitsa kuti zitheke kusintha ziwerengero osati za indexes zokha komanso m'njira zosiyanasiyana (kusintha kwathunthu kapena pang'ono)
  2. zitheke osati kungosankha nkhokwe, komanso ma seva osiyanasiyana (izi ndizabwino kwambiri pakakhala zochitika zambiri za MS SQL Server)
  3. Kuti muzitha kusinthasintha kwambiri pakugwiritsa ntchito, tikulimbikitsidwa kukulunga malamulowo m'malaibulale ndikuwatulutsa ku malamulo a PowerShell, monga momwe amachitira, mwachitsanzo, apa:
  4. dbatools.io/commands
  5. zitheke kupulumutsa ndikusintha makonda anu pa pulogalamu yonseyo ndipo, ngati kuli kofunikira, pagawo lililonse la MS SQL Server ndi database iliyonse.
  6. Kuchokera pa mfundo 2 ndi 4, zikutsatira kuti mukufuna kupanga magulu ndi ma database ndi magulu ndi MS SQL Server zochitika, zomwe makonda ali ofanana.
  7. fufuzani maumboni obwereza (okwanira ndi osakwanira, omwe ali osiyana pang'ono kapena amasiyana m'mizere yophatikizidwa)
  8. Popeza SQLIndexManager imagwiritsidwa ntchito pa MS SQL Server DBMS yokha, ndikofunikira kuwonetsa izi m'dzina, mwachitsanzo, motere: SQLIndexManager ya MS SQL Server.
  9. Sunthani magawo onse omwe si a GUI a pulogalamuyo m'magawo osiyana ndikulembanso mu NET Core 2.1

Panthawi yolemba, chinthu cha 6 cha zomwe akufuna chikukonzedwa mwachangu ndipo pali chithandizo kale munjira yosaka zobwereza zathunthu ndi zofanana:

Ndemanga za chida chaulere cha SQLIndexManager

Zotsatira

Source: www.habr.com

Kuwonjezera ndemanga