ডেটা ক্যাপচার এবং __ $ আপডেট_মাস্ক বাইনারি পরিবর্তন করুন


9

আমরা একটি উত্পাদনের টেবিলে করা পরিবর্তনগুলি ক্যাপচার করতে সিডিসি ব্যবহার করছি। পরিবর্তিত সারিগুলি একটি ডেটা গুদামে (ইনফরমেশন) রফতানি করা হচ্ছে। আমি জানি যে __ $ update_mask কলামটি কী কী কলামগুলি একটি ভের্নারি আকারে আপডেট হয়েছিল তা সঞ্চয় করে। আমি জানি যে এই কলামগুলি কী ছিল সেই মুখোশটি থেকে আমি খুঁজে পেতে বিভিন্ন সিডিসির ফাংশন ব্যবহার করতে পারি ।

আমার প্রশ্ন এই। কেউ কি আমার জন্য সেই মুখোশের পিছনের যুক্তিটি সংজ্ঞায়িত করতে পারেন যাতে আমরা গুদামে পরিবর্তিত কলামগুলি সনাক্ত করতে পারি? যেহেতু আমরা সার্ভারের বাইরে প্রক্রিয়াজাত করছি সেসব এমএসএসকিউএল সিডিসি ফাংশনে আমাদের সহজে অ্যাক্সেস নেই। আমি বরং কোডের মুখোশটি নিজেই ভেঙে ফেলি। এসকিউএল প্রান্তে সিডিসির কার্যকারিতা এই সমাধানের জন্য সমস্যাযুক্ত।

সংক্ষেপে, আমি __ $ আপডেট_মাস্ক ক্ষেত্রটি থেকে হাতে কলমে পরিবর্তিত কলামগুলি সনাক্ত করতে চাই।

হালনাগাদ:

বিকল্প হিসাবে গুদামে পরিবর্তিত কলামগুলির একটি মানব পাঠযোগ্য তালিকা প্রেরণযোগ্যও ছিল accep আমরা দেখতে পেলাম যে এটি আমাদের আসল পদ্ধতির চেয়ে অনেক বেশি পারফরম্যান্সের সাথে সম্পাদিত হতে পারে।

নীচের এই প্রশ্নের সিএলআর উত্তর এই বিকল্পটি পূরণ করে এবং ভবিষ্যতের দর্শকদের জন্য মুখোশটির ব্যাখ্যা দেওয়ার বিশদ অন্তর্ভুক্ত করে। তবে XML PATH ব্যবহার করে গৃহীত উত্তর একই চূড়ান্ত ফলাফলের জন্য এখনও দ্রুততম।


উত্তর:


11

এবং গল্পটির নৈতিকতা হ'ল ... পরীক্ষা, অন্যান্য জিনিস চেষ্টা করে দেখুন, বড় মনে হয়, তারপরে ছোট, সবসময় ধরে নিও এর চেয়ে ভাল উপায় আছে।

আমার শেষ উত্তর হিসাবে বৈজ্ঞানিকভাবে আকর্ষণীয় ছিল। আমি অন্য একটি পদ্ধতির চেষ্টা করার সিদ্ধান্ত নিয়েছে। আমার মনে আছে আমি এক্সএমএল পথ ('') কৌতুক দিয়ে কনক্যাট করতে পারি। যেহেতু আমি জেনেছিলাম যে পূর্ববর্তী উত্তর থেকে ক্যাপচার_কলামের তালিকা থেকে প্রতিটি পরিবর্তিত কলামের অর্ডিনাল কীভাবে পাবেন তা আমি ভেবেছিলাম যে এমএস বিট ফাংশনটি আমাদের যা প্রয়োজন তার জন্য সেভাবে আরও ভালভাবে কাজ করবে কিনা তা পরীক্ষার জন্য উপযুক্ত।

SELECT __$update_mask ,
        ( SELECT    CC.column_name + ','
          FROM      cdc.captured_columns CC
                    INNER JOIN cdc.change_tables CT ON CC.[object_id] = CT.[object_id]
          WHERE     capture_instance = 'dbo_OurTableName'
                    AND sys.fn_cdc_is_bit_set(CC.column_ordinal,
                                              PD.__$update_mask) = 1
        FOR
          XML PATH('')
        ) AS changedcolumns
FROM    cdc.dbo_MyTableName PD

এটি সমস্ত সিএলআর (যদিও মজাদার নয়) এর চেয়ে পরিষ্কার পরিচ্ছন্ন, কেবলমাত্র এসকিউএল কোডটিতে ফিরে আসে। এবং, ড্রাম রোল .... একই ফলাফলটি এক সেকেন্ডেরও কম সময়ে প্রদান করে । যেহেতু উত্পাদনের ডেটা প্রতিটি দ্বিতীয় গণনায় 100 গুণ বড়।

আমি অন্য উত্তরটি বৈজ্ঞানিক উদ্দেশ্যে রেখে দিচ্ছি - তবে আপাতত, এটি আমাদের সঠিক উত্তর।


FROM ধারাটিতে টেবিলের নামটিতে _CT যুক্ত করুন।
ক্রিস মর্লি

1
ফিরে আসার এবং এর উত্তর দেওয়ার জন্য ধন্যবাদ, আমি একটি খুব অনুরূপ সমাধানের সন্ধান করছি যাতে কোনও এসকিউএল কল হয়ে যাওয়ার পরে আমরা কোডের মধ্যে সেই অনুযায়ী ফিল্টার করতে পারি। আমি সিডিসি থেকে ফিরে প্রতিটি সারিতে প্রতিটি কলামের জন্য কল করতে কল্পনা করি না!
নিক0lias

2

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

আমরা এই ক্যোয়ারির সাথে কলামের নাম এবং তাদের মূল অবস্থানগুলির একটি তালিকা পেয়েছি। রিটার্নটি একটি এক্সএমএল ফর্ম্যাটে ফিরে আসে যাতে আমরা এসকিউএল সিএলআরের কাছে যেতে পারি।

DECLARE @colListXML varchar(max);

SET @colListXML = (SELECT column_name, column_ordinal
    FROM  cdc.captured_columns 
    INNER JOIN cdc.change_tables 
    ON captured_columns.[object_id] = change_tables.[object_id]
    WHERE capture_instance = 'dbo_OurTableName'
    FOR XML Auto);

তারপরে আমরা সেই এক্সএমএল ব্লকটিকে একটি চলক হিসাবে এবং মাস্ক ক্ষেত্রকে একটি সিএলআর ফাংশনে পাস করি যা _ $ আপডেট_মাস্ক বাইনারি ক্ষেত্রের পরিবর্তিত কলামগুলির কমা বিস্মৃত স্ট্রিংটি দেয়। এই ক্লার ফাংশনটি এক্সএমএল তালিকার প্রতিটি কলামের পরিবর্তন বিটের জন্য মাস্ক ক্ষেত্রটিকে জিজ্ঞাসাবাদ করে এবং তারপরে সম্পর্কিত অর্ডিনাল থেকে এর নামটি ফিরিয়ে দেয়।

SELECT  cdc.udf_clr_ChangedColumns(@colListXML,
        CAST(__$update_mask AS VARCHAR(MAX))) AS changed
    FROM cdc.dbo_OurCaptureTableName
    WHERE NOT __$update_mask IS NULL;

সি # ক্লার কোডটি দেখতে দেখতে: (সিডিসিটিলিটিস নামক একটি অ্যাসেমব্লিতে সংকলিত)

using System;
using System.Data;
using System.Data.SqlClient;
using System.Data.SqlTypes;
using Microsoft.SqlServer.Server;

public partial class UserDefinedFunctions
{
    [Microsoft.SqlServer.Server.SqlFunction]
    public static SqlString udf_clr_cdcChangedColumns(string columnListXML, string updateMaskString)
    {
        /*  xml of column ordinals shall be formatted as follows:

            <cdc.captured_columns column_name="Column1" column_ordinal="1" />                
            <cdc.captured_columns column_name="Column2" column_ordinal="2" />                

        */

        System.Text.ASCIIEncoding encoding=new System.Text.ASCIIEncoding();
        byte[] updateMask = encoding.GetBytes(updateMaskString);

        string columnList = "";
        System.Xml.XmlDocument colList = new System.Xml.XmlDocument();
        colList.LoadXml("<columns>" + columnListXML + "</columns>"); /* generate xml with root node */

        for (int i = 0; i < colList["columns"].ChildNodes.Count; i++)
        {
            if (columnChanged(updateMask, int.Parse(colList["columns"].ChildNodes[i].Attributes["column_ordinal"].Value)))
            {
                columnList += colList["columns"].ChildNodes[i].Attributes["column_name"].Value + ",";
            }
        }

        if (columnList.LastIndexOf(',') > 0)
        {
            columnList = columnList.Remove(columnList.LastIndexOf(','));   /* get rid of trailing comma */
        }

        return columnList;  /* return the comma seperated list of columns that changed */
    }

    private static bool columnChanged(byte[] updateMask, int colOrdinal)
    {
        unchecked  
        {
            byte relevantByte = updateMask[(updateMask.Length - 1) - ((colOrdinal - 1) / 8)];
            int bitMask = 1 << ((colOrdinal - 1) % 8);  
            var hasChanged = (relevantByte & bitMask) != 0;
            return hasChanged;
        }
    }
}

এবং সিএলআর এর কাছে ফাংশনটি এর মতো:

CREATE FUNCTION [cdc].[udf_clr_ChangedColumns]
       (@columnListXML [nvarchar](max), @updateMask [nvarchar](max))
RETURNS [nvarchar](max) WITH EXECUTE AS CALLER
AS 
EXTERNAL NAME [CDCUtilities].[UserDefinedFunctions].[udf_clr_cdcChangedColumns]

এরপরে আমরা এই কলামের তালিকাটি রো-সেটটিতে যুক্ত করব এবং বিশ্লেষণের জন্য ডেটা গুদামে ছেড়ে দেব। ক্যোয়ারী এবং ক্লারিকে ব্যবহার করে আমরা প্রতি পরিবর্তন প্রতি সারিতে দুটি ফাংশন কল ব্যবহার করা এড়াতে চাই। আমাদের পরিবর্তন ক্যাপচার দৃষ্টান্তের জন্য কাস্টমাইজড ফলাফল সহ আমরা মাংসের ডানদিকে যেতে পারি।

জোন সেগেল যেভাবে মুখোশটি ব্যাখ্যা করতে পারে তার জন্য প্রস্তাবিত এই স্ট্যাকওভারফ্লো পোস্টকে ধন্যবাদ ।

এই পদ্ধতির সাথে আমাদের অভিজ্ঞতায় আমরা 3 সেকেন্ডের নীচে 10 কে সিডিসি সারি থেকে সমস্ত পরিবর্তিত কলামের একটি তালিকা পেতে সক্ষম হয়েছি।


একটি সমাধান নিয়ে ফিরে আসার জন্য ধন্যবাদ, আমি শীঘ্রই এর জন্য ব্যবহার করতে পারি।
মার্ক স্টোরি-স্মিথ

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