Atunwo ti ọpa ọfẹ SQLIndexManager

Bi o ṣe mọ, awọn atọka ṣe ipa pataki ninu DBMS, n pese wiwa ni iyara si awọn igbasilẹ ti o nilo. Ti o ni idi ti o ṣe pataki lati ṣe iṣẹ wọn ni akoko ti akoko. Pupọ awọn ohun elo ni a ti kọ nipa itupalẹ ati iṣapeye, pẹlu lori Intanẹẹti. Fun apẹẹrẹ, koko-ọrọ yii jẹ atunyẹwo laipẹ ni atejade yii.

Ọpọlọpọ awọn sisanwo ati awọn solusan ọfẹ fun eyi. Fun apẹẹrẹ, o wa ti a ti ṣetan ipinnu naa, da lori ọna imudara atọka ti o dara ju.

Nigbamii, jẹ ki a wo ohun elo ọfẹ SQLIndexManager, ti a kọ nipasẹ AlanDenton.

Iyatọ imọ-ẹrọ akọkọ laarin SQLIndexManager ati nọmba awọn analogues miiran ni a fun nipasẹ onkọwe funrararẹ nibi и nibi.

Ninu nkan yii, a yoo wo ita ni iṣẹ akanṣe ati awọn agbara iṣiṣẹ ti ojutu sọfitiwia yii.

Jiroro yi IwUlO nibi.
Ni akoko pupọ, pupọ julọ awọn asọye ati awọn idun ni atunṣe.

Nitorinaa, jẹ ki a lọ ni bayi si IwUlO SQLIndexManager funrararẹ.

Ohun elo naa ti kọ sinu C # .NET Framework 4.5 ni Visual Studio 2017 ati pe o lo DevExpress fun awọn fọọmu:

Atunwo ti ọpa ọfẹ SQLIndexManager

ati pe o dabi eyi:

Atunwo ti ọpa ọfẹ SQLIndexManager

Gbogbo awọn ibeere ti wa ni ipilẹṣẹ ni awọn faili wọnyi:

  1. Ìwé
  2. Ibeere
  3. Ẹrọ ibeere
  4. Alaye olupin

Atunwo ti ọpa ọfẹ SQLIndexManager

Nigbati o ba n sopọ si ibi ipamọ data ati fifiranṣẹ awọn ibeere si DBMS, ohun elo naa ti fowo si bi atẹle:

ApplicationName=”SQLIndexManager”

Nigbati o ba ṣe ifilọlẹ ohun elo naa, window modal yoo ṣii lati ṣafikun asopọ kan:
Atunwo ti ọpa ọfẹ SQLIndexManager

Nibi, ikojọpọ atokọ pipe ti gbogbo awọn iṣẹlẹ olupin MS SQL ti o wa lori awọn nẹtiwọọki agbegbe ko sibẹsibẹ ṣiṣẹ.

O tun le ṣafikun asopọ kan nipa lilo bọtini apa osi lori akojọ aṣayan akọkọ:

Atunwo ti ọpa ọfẹ SQLIndexManager

Nigbamii ti, awọn ibeere atẹle si DBMS yoo ṣe ifilọlẹ:

  1. Gbigba alaye nipa DBMS
    SELECT ProductLevel  = SERVERPROPERTY('ProductLevel')
         , Edition       = SERVERPROPERTY('Edition')
         , ServerVersion = SERVERPROPERTY('ProductVersion')
         , IsSysAdmin    = CAST(IS_SRVROLEMEMBER('sysadmin') AS BIT)
    

  2. Gbigba atokọ ti awọn apoti isura infomesonu ti o wa pẹlu awọn ohun-ini kukuru wọn
    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
    

Lẹhin ṣiṣe awọn iwe afọwọkọ ti o wa loke, window kan yoo han pẹlu alaye kukuru nipa awọn apoti isura infomesonu ti apẹẹrẹ ti a yan ti MS SQL Server:

Atunwo ti ọpa ọfẹ SQLIndexManager

O tọ lati ṣe akiyesi pe alaye ti o gbooro ti han da lori awọn ẹtọ. Ti o ba wa nibẹ sysadmin, lẹhinna o le yan data lati wiwo sys.master_files. Ti ko ba si iru awọn ẹtọ bẹ, lẹhinna data ti o dinku ni a da pada lasan ki o ma ba fa fifalẹ ibeere naa.

Nibi o nilo lati yan awọn apoti isura infomesonu ti iwulo ki o tẹ bọtini “DARA”.

Nigbamii ti, iwe afọwọkọ atẹle ni yoo ṣiṣẹ fun data data kọọkan ti a yan lati ṣe itupalẹ ipo awọn atọka:

Atọka ipo onínọmbà

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

Gẹgẹbi a ti le rii lati awọn ibeere funrararẹ, awọn tabili igba diẹ lo nigbagbogbo. Eyi ni a ṣe ki ko si awọn atunṣeto, ati ninu ọran ti ero nla kan, ero naa le ṣe ipilẹṣẹ ni afiwe nigbati o ba nfi data sii, nitori fifi awọn oniyipada tabili sii ṣee ṣe nikan ni okun kan.

Lẹhin ṣiṣe iwe afọwọkọ ti o wa loke, window kan pẹlu tabili atọka yoo han:

Atunwo ti ọpa ọfẹ SQLIndexManager

O tun le ṣafihan alaye alaye miiran nibi, gẹgẹbi:

  1. database
  2. nọmba ti ruju
  3. ọjọ ati akoko ti o kẹhin ipe
  4. funmorawon
  5. ẹgbẹ faili

abbl.
Awọn agbọrọsọ funrararẹ le ṣe adani:

Atunwo ti ọpa ọfẹ SQLIndexManager

Ninu awọn sẹẹli ti iwe Fix, o le yan iru iṣe ti yoo ṣee ṣe lakoko iṣapeye. Paapaa, nigbati ọlọjẹ ba pari, a yan iṣẹ aiyipada kan da lori awọn eto ti o yan:

Atunwo ti ọpa ọfẹ SQLIndexManager

O gbọdọ yan awọn atọka ti o fẹ fun sisẹ.

Lilo akojọ aṣayan akọkọ, o le ṣafipamọ iwe afọwọkọ naa (bọtini kanna bẹrẹ ilana imudara atọka funrararẹ):

Atunwo ti ọpa ọfẹ SQLIndexManager

ati fi tabili pamọ ni awọn ọna kika oriṣiriṣi (bọtini kanna gba ọ laaye lati ṣii awọn eto alaye fun itupalẹ ati iṣapeye awọn atọka):

Atunwo ti ọpa ọfẹ SQLIndexManager

O tun le ṣe imudojuiwọn alaye naa nipa tite lori bọtini kẹta ni apa osi ni akojọ aṣayan akọkọ lẹgbẹẹ gilasi titobi.

Bọtini pẹlu gilaasi ti o ga julọ gba ọ laaye lati yan awọn apoti isura infomesonu ti o fẹ fun ero.

Lọwọlọwọ ko si eto iranlọwọ okeerẹ. Nitorinaa, tẹ bọtini “?” yoo jẹ ki window modal kan han ti o ni alaye ipilẹ ninu nipa ọja sọfitiwia naa:

Atunwo ti ọpa ọfẹ SQLIndexManager

Ni afikun si ohun gbogbo ti a ṣalaye loke, akojọ aṣayan akọkọ ni ọpa wiwa kan:

Atunwo ti ọpa ọfẹ SQLIndexManager

Nigbati o ba bẹrẹ ilana iṣapeye atọka:

Atunwo ti ọpa ọfẹ SQLIndexManager

O tun le wo akọọlẹ awọn iṣe ti a ṣe ni isalẹ ti window:

Atunwo ti ọpa ọfẹ SQLIndexManager

Ninu ferese awọn eto alaye fun itupalẹ atọka ati iṣapeye, o le tunto awọn aṣayan arekereke diẹ sii:

Atunwo ti ọpa ọfẹ SQLIndexManager

Awọn ibeere fun ohun elo:

  1. jẹ ki o ṣee ṣe lati yan awọn iṣiro imudojuiwọn yiyan kii ṣe fun awọn atọka nikan ati tun ni awọn ọna oriṣiriṣi (imudojuiwọn ni kikun tabi apakan)
  2. jẹ ki o ṣee ṣe kii ṣe lati yan ibi ipamọ data nikan, ṣugbọn awọn olupin oriṣiriṣi tun (eyi jẹ irọrun pupọ nigbati ọpọlọpọ awọn iṣẹlẹ ti MS SQL Server ba wa)
  3. Fun irọrun nla ni lilo, o daba lati fi ipari si awọn aṣẹ ni awọn ile-ikawe ati gbejade wọn si awọn aṣẹ PowerShell, bi o ti ṣe, fun apẹẹrẹ, nibi:
  4. dbatools.io/àṣẹ
  5. jẹ ki o ṣee ṣe lati fipamọ ati yi awọn eto ti ara ẹni pada fun gbogbo ohun elo ati, ti o ba jẹ dandan, fun apẹẹrẹ kọọkan ti MS SQL Server ati data data kọọkan
  6. Lati awọn oju-iwe 2 ati 4 o tẹle pe o fẹ ṣẹda awọn ẹgbẹ nipasẹ awọn apoti isura infomesonu ati awọn ẹgbẹ nipasẹ awọn apẹẹrẹ MS SQL Server, eyiti awọn eto jẹ kanna.
  7. wa awọn atọka ẹda-iwe (pipe ati pe, eyiti o yatọ diẹ tabi yatọ nikan ni awọn ọwọn to wa)
  8. Niwọn igba ti SQLIndexManager ti lo fun MS SQL Server DBMS nikan, o jẹ dandan lati ṣe afihan eyi ni orukọ, fun apẹẹrẹ, gẹgẹbi atẹle: SQLIndexManager fun MS SQL Server
  9. Gbe gbogbo awọn ẹya ti kii ṣe GUI ti ohun elo sinu awọn modulu lọtọ ki o tun kọ wọn sinu .NET Core 2.1

Ni akoko kikọ, nkan 6 ti awọn ifẹ ti wa ni idagbasoke ni itara ati pe atilẹyin tẹlẹ wa ni irisi wiwa pipe ati awọn ẹda-ẹda iru:

Atunwo ti ọpa ọfẹ SQLIndexManager

Awọn orisun

orisun: www.habr.com

Fi ọrọìwòye kun