আমি একটি এসকিউএল সার্ভার 2017 (সিইউ 9) ডাটাবেস পেয়েছি যা কিছু কার্য সম্পাদন সম্পর্কিত সমস্যা প্রদর্শন করে যা আমার বিশ্বাস করে যে সূচকগুলির পরিসংখ্যানগুলি করতে হবে। সমস্যার সমাধানের সময় আমি আবিষ্কার করেছি যে পরিসংখ্যানগুলি আপডেট হয়নি ((অর্থাত ডিবিসিসি শ্যাওপ্যাটিস্টিকসগুলি সমস্ত ন্যূনমূল্য ফিরিয়ে দেবে)।
আমি প্রভাবিত টেবিলের উপর আপডেট আপডেটের পরিসংখ্যান সম্পাদন করেছি এবং যাচাই করেছি যে গতকাল বিকেল ৪ টা ৪৫ মিনিটে শ্যাওপ্যাটিস্টিকস প্রকৃত মানগুলি ফিরিয়ে দিয়েছে। আজ সকাল :00 টা ৪০ মিনিটে পরিসংখ্যানগুলি আবার শূন্য ছিল (নূন্যমূল্যগুলি ফিরিয়ে দেওয়া)।
ক্লায়েন্টটির রক্ষণাবেক্ষণের কাজটি প্রতিদিন সকাল 4:00 টায় চলার জন্য নির্ধারিত হয় যা পুরো ডাটাবেসের বিরুদ্ধে এসপি_আপডেস্টেটস কার্যকর করে ডেটাবেসটির জন্য পুনরায় সূচি দেয়। আমি যাচাই করেছি যে একজন প্রোফাইলার ট্রেসের সাহায্যে পরিসংখ্যানগুলি 4:00 টায় আপডেট হয়।
পরিসংখ্যান কেন খালি থাকবে তা নিয়ে আমি ক্ষতি করছি, এটি কি রক্ষণাবেক্ষণের কাজটি সকাল :00:০০ টা চলবে? এসকিউএল সার্ভারের এই সংস্করণে আমি কী সচেতন নই?
আপনার সহায়তার জন্য আগাম ধন্যবাদ।
অধিক তথ্য:
- অটো আপডেটের পরিসংখ্যান সক্ষম করা আছে।
- অটো আপডেট পরিসংখ্যান অ্যাসিনক্রোনাসলি অক্ষম is
- স্বতঃ বর্ধিত পরিসংখ্যান অক্ষম করা আছে।
পুনর্নির্মাণ স্ক্রিপ্ট (অবরুদ্ধ):
USE DBNAME;
DECLARE @CERTENG_Lock INT
DECLARE @WebSite_Control_ProcessRunning_Lock INT
DECLARE @WebSite_Control_Disabled_Lock INT
DECLARE @LogMessage VARCHAR(1024)
SELECT @CERTENG_Lock = Lock FROM application.CERTENG_Lock
SELECT @WebSite_Control_Disabled_Lock = MAX(CAST(Disabled AS INT)),
@WebSite_Control_ProcessRunning_Lock = MAX(CAST(ProcessRunning AS INT))
FROM application.WebSite_Control
WHERE Webname = 'Reports'
IF(@CERTENG_Lock = 0 AND @WebSite_Control_Disabled_Lock = 0 AND
@WebSite_Control_ProcessRunning_Lock = 0)
BEGIN
EXECUTE Dba.ReIndex
END
ELSE
BEGIN
SET @LogMessage = 'The reindex job did not run because the following locks were set: '
IF(@CERTENG_Lock = 1)
BEGIN
SET @LogMessage = @LogMessage + 'The CERTENG_Lock was set to 1;'
END
IF(@WebSite_Control_Disabled_Lock = 1)
BEGIN
SET @LogMessage = @LogMessage + 'The WebSite_Control_Disabled_Lock was set to 1;'
END
IF(@WebSite_Control_ProcessRunning_Lock = 1)
BEGIN
SET @LogMessage = @LogMessage + 'The WebSite_Control_ProcessRunning_Lock was set to 1;'
END
INSERT INTO [Dba].[ReindexLog] ([LogMessage]) VALUES (@LogMessage)
END
DBA.Reindex
USE [Database]
GO
/****** Object: StoredProcedure [Dba].[ReIndex] Script Date: 12/20/2018 11:15:33 AM ******/
SET ANSI_NULLS ON
GO
SET QUOTED_IDENTIFIER ON
GO
--Create procedure to perform reindexing
ALTER PROCEDURE [Dba].[ReIndex] (
-- Only rebuild if fragmentation is above ___
@REBUILD_FRAGMENTATION_THRESHOLD FLOAT = 30,
-- Or only reorganize if fragmentation is above ___
@REORG_FRAGMENTATION_THRESHOLD FLOAT = 10
)
AS
SET NOCOUNT ON;
DECLARE @WorkingId BIGINT, @ReindexId BIGINT, @Sql VARCHAR(2000);
DECLARE @TableId INT, @IndexId INT;
DECLARE @ExecutionTime DATETIME
SET @ExecutionTime = GETDATE()
-------------Identify tables------------------------------------------------------------
TRUNCATE TABLE Dba.ReindexList;
-- List all the tables and their indexes in the database by the number of rows
-- in order to do the largest tables first.
INSERT INTO Dba.ReindexList (SchemaName, TableName, IndexName, TableId, IndexId, IndexType, NumberOfRows)
SELECT s.NAME AS [SchemaName], t.NAME AS [TableName], i.NAME AS [IndexName], i.object_id, i.index_id, i.type_desc, p.row_count
FROM sys.schemas AS s
INNER JOIN sys.tables AS t
ON t.schema_id = s.schema_id
INNER JOIN sys.indexes AS i
ON i.object_id = t.object_id
INNER JOIN sys.dm_db_partition_stats AS p
ON p.object_id = i.object_id
AND p.index_id = i.index_id
-- Ignore heaps because they can't be rebuilt or reorganized
WHERE i.type_desc != 'HEAP'
-- Skip individual schemas owned by domain accounts
AND charindex('\', s.NAME) = 0
-- Skip DBA schema
AND s.NAME != 'Dba'
ORDER BY p.row_count DESC, s.NAME, t.NAME, i.index_id;
----------------Check fragmentation---------------------------------------------------
DECLARE
-- Separate table to keep track of only the indexes that need to be now
@FragmentationWorkingList TABLE (ReindexId BIGINT NOT NULL PRIMARY KEY CLUSTERED);
INSERT INTO @FragmentationWorkingList (ReindexId)
SELECT r.ReindexId
FROM Dba.ReindexList AS r
-- Skip fragmentation check for this specific index or table?
LEFT JOIN Dba.ReindexSetting AS st
ON st.DatabaseName = db_name()
AND st.SchemaName = r.SchemaName
AND st.TableName = r.TableName
AND st.IndexName IS NULL
LEFT JOIN Dba.ReindexSetting AS si
ON si.DatabaseName = db_name()
AND si.SchemaName = r.SchemaName
AND si.TableName = r.TableName
AND si.IndexName = r.IndexName
WHERE r.IsFragmentationChecked = 'N'
AND r.IsReindexed = 'N'
-- Index setting overrides table setting if both are specified
AND coalesce(si.SkipFragmentationCheck, st.SkipFragmentationCheck, 'N') = 'N'
ORDER BY r.ReindexId;
SELECT @ReindexId = min(w.ReindexId)
FROM @FragmentationWorkingList AS w;
WHILE @ReindexId IS NOT NULL
BEGIN
-- Pull IDs into variables because the physical stats DM function can't
-- cross-apply values from a JOIN.
SELECT @TableId = r.TableId, @IndexId = r.IndexId
FROM Dba.ReindexList AS r
WHERE r.ReindexId = @ReindexId;
-- Load the fragmentation for each index individually
-- with duration-tracking so we can figure out whether or not
-- this is really worthwhile.
UPDATE Dba.ReindexList
SET FragmentationCheckStartTime = getdate()
WHERE ReindexId = @ReindexId;
UPDATE r
SET Fragmentation = p.avg_fragmentation_in_percent
FROM Dba.ReindexList AS r
-- Use LIMITED for fastest scan
INNER JOIN sys.dm_db_index_physical_stats(db_id(), @TableId, @IndexId, NULL, 'LIMITED') AS p
-- Should only return one row for this index
ON 1 = 1
WHERE r.ReindexId = @ReindexId;
UPDATE Dba.ReindexList
SET IsFragmentationChecked = 'Y', FragmentationCheckEndTime = getdate()
WHERE ReindexId = @ReindexId;
SELECT @ReindexId = min(w.ReindexId)
FROM @FragmentationWorkingList AS w
WHERE w.ReindexId > @ReindexId;
END
------------------------------Reindex------------------------------------
DECLARE
-- Separate table to keep track of only the indexes that need to be now
@ReindexWorkingList TABLE (
-- Order differently based on row count and fragmentation
WorkingId BIGINT NOT NULL identity(1, 1) PRIMARY KEY CLUSTERED, ReindexId BIGINT NOT NULL
);
INSERT INTO @ReindexWorkingList (ReindexId)
SELECT r.ReindexId
FROM Dba.ReindexList AS r
-- Skip fragmentation check for this specific index or table?
LEFT JOIN Dba.ReindexSetting AS st
ON st.DatabaseName = db_name()
AND st.SchemaName = r.SchemaName
AND st.TableName = r.TableName
AND st.IndexName IS NULL
LEFT JOIN Dba.ReindexSetting AS si
ON si.DatabaseName = db_name()
AND si.SchemaName = r.SchemaName
AND si.TableName = r.TableName
AND si.IndexName = r.IndexName
WHERE r.IsReindexed = 'N'
-- Index setting overrides table setting if both are specified
AND coalesce(si.SkipReindex, st.SkipReindex, 'N') = 'N'
-- Process tables in order of the most fragmented, largest
AND r.Fragmentation >= @REORG_FRAGMENTATION_THRESHOLD
ORDER BY r.Fragmentation DESC, r.NumberOfRows DESC, r.ReindexId;
SELECT @WorkingId = min(w.WorkingId)
FROM @ReindexWorkingList AS w;
WHILE @WorkingId IS NOT NULL
BEGIN
SELECT @ReindexId = w.ReindexId
FROM @ReindexWorkingList AS w
WHERE w.WorkingId = @WorkingId;
-- Skip index because of low fragmentation?
IF @REORG_FRAGMENTATION_THRESHOLD > (
-- Assume that an index is highly fragmented if the exact %
-- wasn't calculated to save time
SELECT isnull(r.Fragmentation, 100)
FROM Dba.ReindexList AS r
WHERE r.ReindexId = @ReindexId
)
BEGIN
UPDATE Dba.ReindexList
SET IsReindexed = 'Y', IsSkipped = 'Y', ReindexStartTime = getdate(), ReindexEndTime = getdate()
WHERE ReindexId = @ReindexId;
END
-- Rebuild or reorganize...
ELSE
BEGIN
-- Try/catch inside a loop causes slower performance, but reindexing
-- should continue on the next index if an error occurs.
BEGIN TRY
-- Rebuild or reorganize?
-- 1) Ignore heaps
-- 2) Always rebuild a clustered index
-- 3) Rebuild nonclustered if > __, otherwise reorganize it
-- According to Kalen Delaney (http://social.msdn.microsoft.com/Forums/en/sqldatabaseengine/thread/dd612296-5b3a-40f1-829f-c654b835efed),
-- rebuild always updates statistics with FULLSCAN while reorgnize does not.
SELECT @Sql = 'alter index [' + r.IndexName + '] on [' + r.SchemaName + '].[' + r.TableName + '] ' +
CASE WHEN IndexType = 'HEAP' THEN 'rebuild'
WHEN IndexType = 'CLUSTERED' THEN 'rebuild'
WHEN Fragmentation > @REBUILD_FRAGMENTATION_THRESHOLD THEN 'rebuild'
ELSE 'reorganize; update statistics [' + r.SchemaName + '].[' + r.TableName + '] [' + r.IndexName + ']'
END +
-- TODO: Handle partitions properly
';'
FROM Dba.ReindexList AS r
WHERE r.ReindexId = @ReindexId;
UPDATE Dba.ReindexList
SET ReindexStartTime = getdate(), Sql = @Sql
WHERE ReindexId = @ReindexId;
EXECUTE (@sql);
UPDATE Dba.ReindexList
SET ReindexEndTime = getdate(), IsReindexed = 'Y'
WHERE ReindexId = @ReindexId;
END TRY
BEGIN CATCH
UPDATE Dba.ReindexList
SET ReindexEndTime = getdate(),
-- Mark as reindexed to show that an attempt was made...
IsReindexed = 'Y', ErrorNumber = error_number(), ErrorMessage = error_message()
WHERE ReindexId = @ReindexId;
END CATCH
END
SELECT @WorkingId = min(w.WorkingId)
FROM @ReindexWorkingList AS w
WHERE w.WorkingId > @WorkingId;
END
INSERT INTO Dba.ReindexHistory (HistoryTime, TableId, IndexId, SchemaName, TableName, IndexName, IsClustered, IsReindexed, NumberOfRows, Fragmentation)
SELECT isnull(@ExecutionTime, getdate()), l.TableId, l.IndexId, l.SchemaName, l.TableName, l.IndexName,
CASE l.IndexType WHEN 'CLUSTERED' THEN 'Y'
ELSE 'N'
END AS IsClustered,
l.IsReindexed, l.NumberOfRows, l.Fragmentation
FROM Dba.ReindexList AS l
LEFT JOIN Dba.ReindexHistory AS h
ON h.HistoryTime = l.FragmentationCheckStartTime
AND h.TableId = l.TableId
AND h.IndexId = l.IndexId
WHERE h.HistoryTime IS NULL
ORDER BY l.FragmentationCheckStartTime, l.TableId, l.IndexId;
আপডেট: আমি ডাটাবেসের জন্য অটো আপডেট পরিসংখ্যান অক্ষম করেছি এবং গতকাল ম্যানুয়ালি পরিসংখ্যান আপডেট করেছি। আজ সকালে তারা এখনও জনবহুল। আমি ধরে নিই এর অর্থ অটো আপডেটের মধ্যে কিছু খারাপ হচ্ছে।