একটি উপায় master
হ'ল একটি সিস্টেম পদ্ধতি তৈরি করা এবং তারপরে আপনার রক্ষণাবেক্ষণের ডেটাবেজে একটি মোড়ক তৈরি করা। মনে রাখবেন এটি একবারে কেবল একটি ডাটাবেসের জন্য কাজ করবে।
প্রথম, মাস্টার:
USE [master];
GO
CREATE PROCEDURE dbo.sp_GetFragStats -- sp_prefix required
@tableName NVARCHAR(128) = NULL,
@indexID INT = NULL,
@partNumber INT = NULL,
@Mode NVARCHAR(20) = N'DETAILED'
AS
BEGIN
SET NOCOUNT ON;
SELECT
DatabaseName = DB_NAME(),
TableName = t.name,
IndexName = i.name,
IndexID = s.index_id,
PercentFragment = s.avg_fragmentation_in_percent,
TotalFrags = s.fragment_count,
PagesPerFrag = s.avg_fragment_size_in_pages,
NumPages = s.page_count,
IndexType = s.index_type_desc
-- shouldn't s.partition_number be part of the output as well?
FROM sys.tables AS t
INNER JOIN sys.indexes AS i
ON t.[object_id] = i.[object_id]
AND i.index_id = COALESCE(@indexID, i.index_id)
AND t.name = COALESCE(@tableName, t.name)
CROSS APPLY
sys.dm_db_index_physical_stats(DB_ID(), t.[object_id],
i.index_id, @partNumber, @Mode) AS s
WHERE s.avg_fragmentation_in_percent > 10
-- probably also want to filter on minimum page count too
-- do you really care about a table that has 100 pages?
ORDER BY
DatabaseName, TableName, IndexName, PercentFragment DESC;
END
GO
-- needs to be marked as a system object:
EXEC sp_MS_MarkSystemObject N'dbo.sp_GetFragStats';
GO
এখন, আপনার রক্ষণাবেক্ষণের ডাটাবেসে একটি প্রচ্ছদ তৈরি করুন যা প্রসঙ্গটি সঠিকভাবে সেট করতে ডায়নামিক এসকিউএল ব্যবহার করে:
USE YourMaintenanceDatabase;
GO
CREATE PROCEDURE dbo.GetFragStats
@DatabaseName SYSNAME, -- can't really be NULL, right?
@tableName NVARCHAR(128) = NULL,
@indexID INT = NULL,
@partNumber INT = NULL,
@Mode NVARCHAR(20) = N'DETAILED'
AS
BEGIN
DECLARE @sql NVARCHAR(MAX);
SET @sql = N'USE ' + QUOTENAME(@DatabaseName) + ';
EXEC dbo.sp_GetFragStats @tableName, @indexID, @partNumber, @Mode;';
EXEC sp_executesql
@sql,
N'@tableName NVARCHAR(128),@indexID INT,@partNumber INT,@Mode NVARCHAR(20)',
@tableName, @indexID, @partNumber, @Mode;
END
GO
(ডাটাবেসটির নামটি সত্যিকার অর্থে না হওয়ার NULL
কারণ হ'ল কারণ আপনি প্রতিটি ডেটাবেজে স্বতন্ত্রভাবে উপস্থিত থাকতে পারেন sys.objects
এবং sys.indexes
যেহেতু আপনি উদাহরণস্বরূপ তথ্য চান তবে আলাদা পদ্ধতি থাকতে পারে if)
এখন আপনি এটি অন্য কোনও ডাটাবেসের জন্য কল করতে পারেন, যেমন
EXEC YourMaintenanceDatabase.dbo.GetFragStats
@DatabaseName = N'AdventureWorks2012',
@TableName = N'SalesOrderHeader';
এবং আপনি সর্বদা synonym
প্রতিটি ডাটাবেসে একটি তৈরি করতে পারেন যাতে আপনার রক্ষণাবেক্ষণের ডাটাবেসের নামটিও উল্লেখ করতে হয় না:
USE SomeOtherDatabase;`enter code here`
GO
CREATE SYNONYM dbo.GetFragStats FOR YourMaintenanceDatabase.dbo.GetFragStats;
আর একটি উপায় হ'ল ডায়নামিক এসকিউএল ব্যবহার করা হবে তবে এটিও একবারে কেবল একটি ডাটাবেসের জন্য কাজ করবে:
USE YourMaintenanceDatabase;
GO
CREATE PROCEDURE dbo.GetFragStats
@DatabaseName SYSNAME,
@tableName NVARCHAR(128) = NULL,
@indexID INT = NULL,
@partNumber INT = NULL,
@Mode NVARCHAR(20) = N'DETAILED'
AS
BEGIN
SET NOCOUNT ON;
DECLARE @sql NVARCHAR(MAX) = N'SELECT
DatabaseName = @DatabaseName,
TableName = t.name,
IndexName = i.name,
IndexID = s.index_id,
PercentFragment = s.avg_fragmentation_in_percent,
TotalFrags = s.fragment_count,
PagesPerFrag = s.avg_fragment_size_in_pages,
NumPages = s.page_count,
IndexType = s.index_type_desc
FROM ' + QUOTENAME(@DatabaseName) + '.sys.tables AS t
INNER JOIN ' + QUOTENAME(@DatabaseName) + '.sys.indexes AS i
ON t.[object_id] = i.[object_id]
AND i.index_id = COALESCE(@indexID, i.index_id)
AND t.name = COALESCE(@tableName, t.name)
CROSS APPLY
' + QUOTENAME(@DatabaseName) + '.sys.dm_db_index_physical_stats(
DB_ID(@DatabaseName), t.[object_id], i.index_id, @partNumber, @Mode) AS s
WHERE s.avg_fragmentation_in_percent > 10
ORDER BY
DatabaseName, TableName, IndexName, PercentFragment DESC;';
EXEC sp_executesql @sql,
N'@DatabaseName SYSNAME, @tableName NVARCHAR(128), @indexID INT,
@partNumber INT, @Mode NVARCHAR(20)',
@DatabaseName, @tableName, @indexID, @partNumber, @Mode;
END
GO
তবুও অন্য উপায়টি হ'ল আপনার সমস্ত ডাটাবেসের টেবিল এবং সূচীর নামগুলি একত্র করার জন্য একটি ভিউ (বা টেবিলের মূল্যবান ফাংশন) তৈরি করা হবে তবে আপনাকে ডাটাবেসের নামগুলি ভিউতে হার্ড-কোড করতে হবে এবং যুক্ত করার সাথে সাথে সেগুলি বজায় রাখতে হবে / এই ডাটাবেসগুলিকে অন্তর্ভুক্ত করার জন্য আপনি যে ডেটাবেসগুলি মঞ্জুর করতে চান তা সরিয়ে ফেলুন। এটি অন্যদের মত নয়, আপনাকে একসাথে একাধিক ডাটাবেসের জন্য পরিসংখ্যান পুনরুদ্ধার করতে দেয়।
প্রথম, দেখুন:
CREATE VIEW dbo.CertainTablesAndIndexes
AS
SELECT
db = N'AdventureWorks2012',
t.[object_id],
[table] = t.name,
i.index_id,
[index] = i.name
FROM AdventureWorks2012.sys.tables AS t
INNER JOIN AdventureWorks2012.sys.indexes AS i
ON t.[object_id] = i.[object_id]
UNION ALL
SELECT
db = N'database2',
t.[object_id],
[table] = t.name,
i.index_id,
[index] = i.name
FROM database2.sys.tables AS t
INNER JOIN database2.sys.indexes AS i
ON t.[object_id] = i.[object_id]
-- ... UNION ALL ...
;
GO
তারপরে পদ্ধতি:
CREATE PROCEDURE dbo.GetFragStats
@DatabaseName NVARCHAR(128) = NULL,
@tableName NVARCHAR(128) = NULL,
@indexID INT = NULL,
@partNumber INT = NULL,
@Mode NVARCHAR(20) = N'DETAILED'
AS
BEGIN
SET NOCOUNT ON;
SELECT
DatabaseName = DB_NAME(s.database_id),
TableName = v.[table],
IndexName = v.[index],
IndexID = s.index_id,
PercentFragment = s.avg_fragmentation_in_percent,
TotalFrags = s.fragment_count,
PagesPerFrag = s.avg_fragment_size_in_pages,
NumPages = s.page_count,
IndexType = s.index_type_desc
FROM dbo.CertainTablesAndIndexes AS v
CROSS APPLY sys.dm_db_index_physical_stats
(DB_ID(v.db), v.[object_id], v.index_id, @partNumber, @Mode) AS s
WHERE s.avg_fragmentation_in_percent > 10
AND v.index_id = COALESCE(@indexID, v.index_id)
AND v.[table] = COALESCE(@tableName, v.[table])
AND v.db = COALESCE(@DatabaseName, v.db)
ORDER BY
DatabaseName, TableName, IndexName, PercentFragment DESC;
END
GO