কলিং ডাটাবেস প্রসঙ্গে কার্যকর করতে কেন্দ্রীয় সঞ্চিত পদ্ধতি


17

আমি sys.dm_db_index_physical_statsভিউটি ব্যবহার করে একটি কাস্টমাইজড রক্ষণাবেক্ষণ সমাধানে কাজ করছি । আমার কাছে বর্তমানে এটি একটি সঞ্চিত পদ্ধতি থেকে উল্লেখ করা হচ্ছে। এখন যখন সেই সঞ্চিত প্রক্রিয়াটি আমার একটি ডাটাবেসে চলে, আমি যা করতে চাই তা করে এবং কোনও ডাটাবেস সম্পর্কিত সমস্ত রেকর্ডের তালিকা নীচে টান দেয়। আমি যখন এটি অন্য একটি ডাটাবেসে রাখি তবে এটি কেবল সেই ডিবি সম্পর্কিত সমস্ত রেকর্ডের তালিকা নীচে টান দেয়।

উদাহরণস্বরূপ (নীচে কোড):

  • ডেটাবেস 6 এর বিরুদ্ধে রান করা ক্যোয়ারী 1-10-তে ডাটাবেসের জন্য [অনুরোধ করা] তথ্য প্রদর্শন করে।
  • ডাটাবেস 3 এর বিরুদ্ধে রান করা ক্যোয়ারী কেবলমাত্র ডাটাবেস 3 এর জন্য [অনুরোধ করা] তথ্য দেখায়।

তিনটি ডাটাবেসে বিশেষত এই পদ্ধতিটি আমি চাই কারণ আমি সমস্ত রক্ষণাবেক্ষণের জিনিসগুলিকে একই ডাটাবেসের মধ্যে রাখতে পছন্দ করি। আমি এই কাজটি রক্ষণাবেক্ষণের ডেটাবেজে বসে থাকতে চাই এবং সেই অ্যাপ্লিকেশন ডেটাবেজে থাকি এমনভাবে কাজ করতে চাই।

কোড:

ALTER PROCEDURE [dbo].[GetFragStats] 
    @databaseName   NVARCHAR(64) = NULL
    ,@tableName     NVARCHAR(64) = NULL
    ,@indexID       INT          = NULL
    ,@partNumber    INT          = NULL
    ,@Mode          NVARCHAR(64) = 'DETAILED'
AS
BEGIN
    SET NOCOUNT ON;

    DECLARE @databaseID INT, @tableID INT

    IF @databaseName IS NOT NULL
        AND @databaseName NOT IN ('tempdb','ReportServerTempDB')
    BEGIN
        SET @databaseID = DB_ID(@databaseName)
    END

    IF @tableName IS NOT NULL
    BEGIN
        SET @tableID = OBJECT_ID(@tableName)
    END

    SELECT D.name AS DatabaseName,
      T.name AS TableName,
      I.name AS IndexName,
      S.index_id AS IndexID,
      S.avg_fragmentation_in_percent AS PercentFragment,
      S.fragment_count AS TotalFrags,
      S.avg_fragment_size_in_pages AS PagesPerFrag,
      S.page_count AS NumPages,
      S.index_type_desc AS IndexType
    FROM sys.dm_db_index_physical_stats(@databaseID, @tableID, 
           @indexID, @partNumber, @Mode) AS S
    JOIN 
       sys.databases AS D ON S.database_id = D.database_id
    JOIN 
       sys.tables AS T ON S.object_id = T.object_id
    JOIN 
       sys.indexes AS I ON S.object_id = I.object_id
                        AND S.index_id = I.index_id
    WHERE 
        S.avg_fragmentation_in_percent > 10
    ORDER BY 
        DatabaseName, TableName, IndexName, PercentFragment DESC    
END
GO

4
@ জোয়াচিমআইসাকসন মনে করছেন যে প্রশ্নগুলি কীভাবে তাদের রক্ষণাবেক্ষণের ডাটাবেজে পদ্ধতির একটি অনুলিপি রাখে, যা প্রতিটি ডাটাবেজে প্রক্রিয়াটির একটি অনুলিপি রাখার পরিবর্তে অন্যান্য ডাটাবেসে ডিএমভির উল্লেখ করে।
অ্যারন বারট্র্যান্ড

দুঃখিত আমি আরও স্পষ্ট ছিল না, কয়েক দিন ধরে এই তাকিয়ে ছিল। হারুন স্পট ইন। আমি চাই এই এসপিটি আমার রক্ষণাবেক্ষণের ডাটাবেসে সার্ভার জুড়ে ডেটা দখল করার ক্ষমতা সহ বসুক। এটি যেমন দাঁড়িয়েছে, যখন এটি আমার রক্ষণাবেক্ষণ ডিবিতে বসে, এটি কেবল রক্ষণাবেক্ষণ ডিবি সম্পর্কে খণ্ডিত ডেটা টেনে তোলে। আমি যে বিষয়টি নিয়ে বিভ্রান্ত হয়েছি তা কেন, যখন আমি এই সঠিক একই এসপিটিকে অন্য একটি ডাটাবেসে রাখি এবং এটি একইরূপে চালিত করি, এটি সার্ভার জুড়ে এটি খণ্ডিত ডেটা টানবে না? এই এসপিকে রক্ষণাবেক্ষণ ডিবি থেকে যেমন পরিচালনা করার জন্য এমন কোনও সেটিং বা সুযোগ সুবিধা পরিবর্তিত করা দরকার?

(দ্রষ্টব্য আপনার বর্তমান পদ্ধতির আসলে একই নামের দুটি টেবিল দুটি ভিন্ন স্কিমের অধীনে হতে পারে যে উপেক্ষা করে যে -। আমার উত্তর এ প্রস্তাবনা আপনি ইনপুট এবং / অথবা আউটপুট অংশ হিসেবে স্কিমা নাম বিবেচনা করতে পারেন ছাড়াও)
অ্যারন বারট্র্যান্ড

উত্তর:


15

একটি উপায় 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

15

ঠিক আছে, খারাপ খবর আছে, একটি ক্যাচ সহ ভাল খবর এবং কিছু সত্যই ভাল খবর।

খারাপ খবর

টি-এসকিউএল অবজেক্টগুলি যেখানে থাকে সেগুলি ডাটাবেসে চালিত করে। দুটি (খুব দরকারী নয়) ব্যতিক্রম রয়েছে:

  1. ডাটাবেসে প্রিফিক্সড নামের সাথে সঞ্চিত প্রক্রিয়াগুলি sp_এবং এটি [master]ডাটাবেসে বিদ্যমান (কোনও দুর্দান্ত বিকল্প নয়: একটি সময়ে একটি ডিবি, কিছু যুক্ত করে [master], সম্ভবত প্রতিটি ডিবিতে প্রতিশব্দ যুক্ত করে, যা প্রতিটি নতুন ডিবিতে করতে হবে)
  2. অস্থায়ী সঞ্চিত পদ্ধতি - স্থানীয় এবং বিশ্বব্যাপী (প্রতিটি সময় তৈরি করতে হবে এমন কোনও ব্যবহারিক বিকল্প নয় এবং আপনার sp_সঞ্চিত সংগ্রহের সাথে থাকা একই সমস্যাগুলি আপনাকে ছেড়ে দেবে [master]

সুসংবাদ (একটি ক্যাচ সহ)

অনেকগুলি (সম্ভবত সবচেয়ে?) লোকেরা কিছু সত্যই সাধারণ মেটা-ডেটা পেতে অন্তর্নির্মিত ফাংশন সম্পর্কে সচেতন:

এই ফাংশনগুলি ব্যবহার করে জিনদের sys.databases(যদিও এটি আসলে কোনও সমস্যা নয়), sys.objects(সূচক sys.tablesদৃষ্টিভঙ্গি বাদ দেওয়া পছন্দসই ) এবং এবং sys.schemas(আপনি যেটি অনুপস্থিত ছিলেন, এবং সমস্ত কিছুই dboস্কিমাতে নেই ;-) এর প্রয়োজনীয়তা দূর করতে পারে। তবে চারটি জোইনের মধ্যে তিনটি সরানোর পরেও আমরা এখনও একই জায়গায় ঠিক একই জায়গায় রয়েছি? ভুল-হে!

চমৎকার বৈশিষ্ট্য হল OBJECT_NAME()এবং OBJECT_SCHEMA_NAME()ফাংশন তারা একটি ঐচ্ছিক দ্বিতীয় প্যারামিটারটি আছে হয় @database_id। অর্থ, যখন এই টেবিলগুলিতে যোগদান করা (ব্যতীত sys.databases) ডাটাবেস-নির্দিষ্ট, এই ফাংশনগুলি ব্যবহার করে আপনি সার্ভার-ওয়াইড তথ্য পাবেন। এমনকি OBJECT_ID () সার্ভার-বিস্তৃত তথ্যের জন্য এটি একটি পুরোপুরি যোগ্যতাযুক্ত বস্তুর নাম দিয়ে মঞ্জুরি দেয়।

এই মেটা-ডেটা ফাংশনগুলিকে মূল ক্যোয়ারিতে অন্তর্ভুক্ত করে আমরা একইসাথে বর্তমান ডাটাবেস ছাড়িয়ে প্রসারিত করার সময় সহজ করতে পারি। রিফ্যাক্টরিংয়ের প্রথম-পাসটি কোয়েরিটি দেয়:

SELECT  DB_NAME(stat.database_id) AS [DatabaseName],
        OBJECT_SCHEMA_NAME(stat.[object_id], stat.database_id) AS [SchemaName],
        OBJECT_NAME(stat.[object_id], stat.database_id) AS [TableName],
        ind.name AS [IndexName],
        stat.index_id AS [IndexID],
        stat.avg_fragmentation_in_percent AS [PercentFragment],
        stat.fragment_count AS [TotalFrags],
        stat.avg_fragment_size_in_pages AS [PagesPerFrag],
        stat.page_count AS [NumPages],
        stat.index_type_desc AS [IndexType]
FROM sys.dm_db_index_physical_stats(@DatabaseID, @TableID, 
        @IndexID, @PartitionNumber, @Mode) stat
INNER JOIN sys.indexes ind
        ON ind.[object_id] = stat.[object_id]
       AND ind.[index_id] = stat.[index_id]
WHERE stat.avg_fragmentation_in_percent > 10
ORDER BY DatabaseName, TableName, IndexName, PercentFragment DESC;

এবং এখন "ধরা" এর জন্য: সূচকের নামগুলি পাওয়ার জন্য কোনও মেটা-ডেটা ফাংশন নেই, সার্ভার-ওয়াইড একা থাকুক। তাহলে কি তাই? আমরা কি 90% সম্পূর্ণ এবং এখনও sys.indexesতথ্যের জন্য নির্দিষ্ট ডাটাবেসে থাকা দরকার আটকেছি ? জনসংখ্যার জন্য ডায়নামিক এসকিউএল ব্যবহার করার জন্য আমাদের কী সত্যই কোনও স্টোরেজ পদ্ধতি তৈরি করতে হবে, প্রতিবার যখন আমাদের মূল প্রকোপটি চালিত হয়, sys.indexesসমস্ত ডাটাবেস জুড়ে সমস্ত প্রবেশের টেম্প টেবিল যাতে আমরা এতে যোগ দিতে পারি? না!

সত্যিই ভাল খবর

সুতরাং বরাবর একটি সামান্য বৈশিষ্ট্য আসে যা কিছু লোকেরা ঘৃণা করতে পছন্দ করে তবে সঠিকভাবে ব্যবহার করা গেলে কিছু আশ্চর্যজনক কাজ করতে পারে। হ্যাঁ: এসকিউএলসিআরআর। কেন? কারণ SQLCLR ফাংশন স্পষ্টত এসকিউএল স্টেটমেন্ট জমা দিতে পারেন, কিন্তু অ্যাপ্লিকেশনটি কোড থেকে জমা দেওয়ার খুব প্রকৃতি দ্বারা, এটা হয় ডায়নামিক এসকিউএল। সুতরাং টি-এসকিউএল ফাংশনগুলির বিপরীতে, এসকিউএলসিআরআর ফাংশনগুলি কার্যকর করার আগে কোয়েরিতে একটি ডাটাবেসের নাম ইনজেক্ট করতে পারে। অর্থ, আমরা আমাদের নিজস্ব ফাংশনের ক্ষমতা মিরর করতে তৈরি করতে পারেন OBJECT_NAME()এবং OBJECT_SCHEMA_NAME()একটি নিতে database_idএবং যে ডাটাবেসের জন্য তথ্য পান।

নিম্নলিখিত কোডটি হল সেই ফাংশন। তবে এটি আইডির পরিবর্তে একটি ডাটাবেসের নাম নেয় যাতে এটির সন্ধানের অতিরিক্ত পদক্ষেপের প্রয়োজন হয় না (এটি এটিকে কিছুটা জটিল এবং আরও দ্রুততর করে তোলে)।

public class MetaDataFunctions
{
    [return: SqlFacet(MaxSize = 128)]
    [Microsoft.SqlServer.Server.SqlFunction(IsDeterministic = true, IsPrecise = true,
        SystemDataAccess = SystemDataAccessKind.Read)]
    public static SqlString IndexName([SqlFacet(MaxSize = 128)] SqlString DatabaseName,
        SqlInt32 ObjectID, SqlInt32 IndexID)
    {
        string _IndexName = @"<unknown>";

        using (SqlConnection _Connection =
                                    new SqlConnection("Context Connection = true;"))
        {
            using (SqlCommand _Command = _Connection.CreateCommand())
            {
                _Command.CommandText = @"
SELECT @IndexName = si.[name]
FROM   [" + DatabaseName.Value + @"].[sys].[indexes] si
WHERE  si.[object_id] = @ObjectID
AND    si.[index_id] = @IndexID;
";

                SqlParameter _ParamObjectID = new SqlParameter("@ObjectID",
                                               SqlDbType.Int);
                _ParamObjectID.Value = ObjectID.Value;
                _Command.Parameters.Add(_ParamObjectID);

               SqlParameter _ParamIndexID = new SqlParameter("@IndexID", SqlDbType.Int);
                _ParamIndexID.Value = IndexID.Value;
                _Command.Parameters.Add(_ParamIndexID);

                SqlParameter _ParamIndexName = new SqlParameter("@IndexName",
                                                  SqlDbType.NVarChar, 128);
                _ParamIndexName.Direction = ParameterDirection.Output;
                _Command.Parameters.Add(_ParamIndexName);

                _Connection.Open();
                _Command.ExecuteNonQuery();

                if (_ParamIndexName.Value != DBNull.Value)
                {
                    _IndexName = (string)_ParamIndexName.Value;
                }
            }
        }

        return _IndexName;
    }
}

আপনি যদি খেয়াল করেন, আমরা প্রসঙ্গ সংযোগটি ব্যবহার করছি, যা কেবল দ্রুত নয়, এটি SAFEঅ্যাসেমব্লিতেও কাজ করে । হ্যাঁ, এটি হিসাবে চিহ্নিত হিসাবে একটি বিধানসভাতে কাজ করেSAFE, সুতরাং এটি (বা এর বিভিন্নতা) এমনকি Azure এসকিউএল ডেটাবেস ভি 12 এও কাজ করা উচিত (এসকিউএলসিআরআর'র সমর্থন এপ্রিল, ২০১ in-এ অ্যাজুরে এসকিউএল ডেটাবেস থেকে বরং আকস্মিকভাবে সরানো হয়েছিল)

সুতরাং মূল প্রশ্নের সাথে আমাদের দ্বিতীয় পাসের রিফ্যাক্টরিং আমাদের নিম্নলিখিতটি দেয়:

SELECT  DB_NAME(stat.database_id) AS [DatabaseName],
        OBJECT_SCHEMA_NAME(stat.[object_id], stat.database_id) AS [SchemaName],
        OBJECT_NAME(stat.[object_id], stat.database_id) AS [TableName],
        dbo.IndexName(DB_NAME(stat.database_id), stat.[object_id], stat.[index_id])
                     AS [IndexName],
        stat.index_id AS [IndexID],
        stat.avg_fragmentation_in_percent AS [PercentFragment],
        stat.fragment_count AS [TotalFrags],
        stat.avg_fragment_size_in_pages AS [PagesPerFrag],
        stat.page_count AS [NumPages],
        stat.index_type_desc AS [IndexType]
FROM sys.dm_db_index_physical_stats(@DatabaseID, @TableID, 
        @IndexID, @PartitionNumber, @Mode) stat
WHERE stat.avg_fragmentation_in_percent > 10
ORDER BY DatabaseName, TableName, IndexName, PercentFragment DESC;

এটাই! এই এসকিউএলসিআরআর স্কেলার ইউডিএফ এবং আপনার রক্ষণাবেক্ষণ টি-এসকিউএল স্টোরেড পদ্ধতি উভয়ই একই কেন্দ্রীয়ীকৃত [maintenance]ডাটাবেসে বাস করতে পারে । এবং, আপনাকে একবারে একটি ডাটাবেস প্রক্রিয়া করতে হবে না; সার্ভার-ওয়াইড সমস্ত নির্ভরশীল তথ্যের জন্য এখন আপনার কাছে মেটা-ডেটা ফাংশন রয়েছে।

PS .IsNullটি-এসকিউএল র‍্যাপার অবজেক্টটি WITH RETURNS NULL ON NULL INPUTবিকল্পের সাহায্যে তৈরি করা উচিত হওয়ায় সি # কোডে ইনপুট পরামিতিগুলির কোনও চেকিং নেই :

CREATE FUNCTION [dbo].[IndexName]
                   (@DatabaseName [nvarchar](128), @ObjectID [int], @IndexID [int])
RETURNS [nvarchar](128) WITH EXECUTE AS CALLER, RETURNS NULL ON NULL INPUT
AS EXTERNAL NAME [{AssemblyName}].[MetaDataFunctions].[IndexName];

অতিরিক্ত নোট:

  • এখানে বর্ণিত পদ্ধতিটি ক্রস-ডাটাবেস মেটা-ডেটা ফাংশনগুলির অনুপস্থিত, অন্যান্য, খুব একই রকম সমস্যা সমাধানের জন্যও ব্যবহার করা যেতে পারে। নিম্নলিখিত মাইক্রোসফ্ট কানেক্ট পরামর্শ যেমন একটি ক্ষেত্রে একটি উদাহরণ। এবং, মাইক্রোসফ্ট "উইন্ট ফিক্স" হিসাবে এটি বন্ধ করে দিয়েছে তা দেখে স্পষ্ট যে তারা OBJECT_NAME()এই প্রয়োজনীয়তাটি পূরণ করার মতো বিল্ট-ইন ফাংশন সরবরাহ করতে আগ্রহী নয় (অতএব সেই পরামর্শটি :-) এ পোস্ট করা ওয়ার্করাউন্ড)।

    Hobt_id থেকে অবজেক্টের নাম পেতে মেটাডেটা ফাংশন যুক্ত করুন

  • এসকিউএলসিআরআর ব্যবহার সম্পর্কে আরও জানার জন্য, দয়া করে এসকিউএল সার্ভার সেন্ট্রিয়ায় আমি লিখছি সিঁড়ি থেকে এসকিউএলসিআরআর সিরিজটি দেখুন (নিখরচায় নিবন্ধকরণ প্রয়োজন; দুঃখিত, আমি সেই সাইটের নীতিগুলি নিয়ন্ত্রণ করি না)।

  • IndexName()উপরে দেখানো SQLCLR ফাংশন Pastebin উপর একটি সহজ-থেকে-ইনস্টল স্ক্রিপ্টের মধ্যে, উপলব্ধ প্রাক কম্পাইল করা হয়। স্ক্রিপ্টটি "সিএলআর ইন্টিগ্রেশন" বৈশিষ্ট্যটিকে সক্ষম করে যদি এটি ইতিমধ্যে সক্ষম না থাকে এবং সমাবেশটি চিহ্নিত করা থাকে SAFE। এটি .NET ফ্রেমওয়ার্ক সংস্করণ 2.0 এর বিপরীতে সংকলিত হয়েছে যাতে এটি এসকিউএল সার্ভার 2005 এবং আরও নতুন (যেমন এসকিউএলসিআরআর সমর্থন করে এমন সমস্ত সংস্করণ) এ কাজ করবে।

    ক্রস-ডাটাবেস ইনডেক্সনামের জন্য এসকিউএলসিআরআর মেটা-ডেটা ফাংশন ()

  • যদি কেউ IndexName()এসকিউএলসিআরআর ফাংশন এবং 320 টিরও বেশি ফাংশন এবং সঞ্চিত পদ্ধতিতে আগ্রহী হন তবে এটি এসকিউএল # লাইব্রেরিতে (যা আমি এর লেখক) এ উপলব্ধ। দয়া করে মনে রাখবেন যে একটি ফ্রি সংস্করণ থাকাকালীন, Sys_IndexName ফাংশনটি কেবলমাত্র সম্পূর্ণ সংস্করণে উপলব্ধ (একই রকম সিস_অ্যাস্পব্লায়নেম ফাংশন সহ)।

আমাদের সাইট ব্যবহার করে, আপনি স্বীকার করেছেন যে আপনি আমাদের কুকি নীতি এবং গোপনীয়তা নীতিটি পড়েছেন এবং বুঝতে পেরেছেন ।
Licensed under cc by-sa 3.0 with attribution required.