ডেটা শুদ্ধ করার দ্রুততম উপায় কী?


18

দৃশ্যপট:

আমরা দুই টেবিল আছে Tbl1& Tbl2গ্রাহক সার্ভার উপর। Tbl1প্রকাশক থেকে প্রতিলিপি করা হচ্ছে Server Aএবং এটি দুই ট্রিগার আছে - সন্নিবেশ ও আপডেট। ট্রিগারগুলি এতে ডেটা serোকানো এবং আপডেট করছে Tbl2

এখন, আমাদের শুদ্ধ করতে হবে (আনুমানিক 900 মিলিয়ন রেকর্ডস) Tbl2যা থেকে মোট 1000+ মিলিয়ন রেকর্ড রয়েছে। নীচে এক মাস থেকে এক মিনিটের ডেটা বিতরণ করা হবে।

  • এক মাস - 14986826 সারি
  • একদিন - 483446 সারি
  • এক ঘন্টা - 20143 সারি
  • এক মিনিট - 335 সারি

আমি যা খুঁজছি;

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

পদক্ষেপ:

  1. বিসিপি বিদ্যমান সারণী টিবিএল 2 থেকে প্রয়োজনীয় ডেটা বের করে (প্রায় 100 মিলিয়ন রেকর্ড, এটি প্রায় 30 মিনিট সময় নিতে পারে)।
    • ধরা যাক আমি 1Fab2018 10:00 অপরাহ্নে কার্যকলাপটি শুরু করেছি, এটি 1Fab2018 10:30 এ শেষ হয়েছে। সময়ের ক্রিয়াকলাপটি শেষ হওয়ার পরে, টেবিল টিবিএল 2 নতুন রেকর্ডগুলি পাবে যা ডেল্টায় পরিণত হয়
  2. Tbl3 নাম সহ ডাটাবেসে একটি নতুন টেবিল তৈরি করুন
  3. সদ্য নির্মিত টেবিল টিবিএল 3-তে রফতানি হওয়া তথ্যের মধ্যে বিসিপি (প্রায় 100 মিলিয়ন রেকর্ড, এটি প্রায় 30 মিনিট সময় নিতে পারে)
  4. প্রতিলিপি কাজ বন্ধ করুন
  5. একবার বিসিপি-ইন সম্পূর্ণ হয়ে গেলে, নতুন ব-দ্বীপের ডেটা sertোকাতে tsql স্ক্রিপ্ট ব্যবহার করুন।

  6. চ্যালেঞ্জটি হ'ল ডেল্টা "আপডেট" বিবৃতিটি কীভাবে মোকাবেলা করতে হবে?

  7. প্রতিলিপি শুরু করুন

অতিরিক্ত প্রশ্ন:

পরিস্থিতি মোকাবেলার সেরা উপায় কী?

উত্তর:


26

যেহেতু আপনি 90% সারি মুছে ফেলছেন, তাই আমি একই কাঠামো সহ একটি নতুন টেবিলের মধ্যে থাকা সারিগুলি অনুলিপি করার পরামর্শ দিই, তারপরে ALTER TABLE ... SWITCHবিদ্যমান টেবিলটি নতুন টেবিলের সাথে প্রতিস্থাপন করতে ব্যবহার করুন , তারপরে কেবল পুরানো টেবিলটি ফেলে দিন। সিনট্যাক্সের জন্য এই মাইক্রোসফ্ট ডক্স পৃষ্ঠাটি দেখুন ।

একটি সাধারণ পরীক্ষা-বিছানা, অনুলিপি ছাড়াই যা সাধারণ নীতিটি দেখায়:

প্রথমত, আমরা আমাদের পরীক্ষার জন্য একটি ডাটাবেস তৈরি করব:

USE master;
IF (SELECT 1 FROM sys.databases d WHERE d.name = 'SwitchTest') IS NOT NULL
BEGIN
    ALTER DATABASE SwitchTest SET SINGLE_USER WITH ROLLBACK IMMEDIATE;
    DROP DATABASE SwitchTest;
END
CREATE DATABASE SwitchTest;
ALTER DATABASE SwitchTest SET RECOVERY FULL;
BACKUP DATABASE SwitchTest TO DISK = 'NUL:';
GO

এখানে, আমরা আপনার সেটআপটি প্রায় অনুমান করে টেবিল "এ" থেকে "বি" তে সারি সরিয়ে নিয়ে যাওয়ার ট্রিগার সহ কয়েকটি টেবিল তৈরি করি।

USE SwitchTest;
GO
CREATE TABLE dbo.A
(
    i int NOT NULL 
        CONSTRAINT PK_A
        PRIMARY KEY CLUSTERED
        IDENTITY(1,1)
    , d varchar(300) NOT NULL
    , rowdate datetime NOT NULL
) ON [PRIMARY]
WITH (DATA_COMPRESSION = PAGE);

CREATE TABLE dbo.B
(
    i int NOT NULL 
        CONSTRAINT PK_B
        PRIMARY KEY CLUSTERED
    , d varchar(300) NOT NULL
    , rowdate datetime NOT NULL
) ON [PRIMARY]
WITH (DATA_COMPRESSION = PAGE);

GO
CREATE TRIGGER t_a
ON dbo.A
AFTER INSERT, UPDATE
AS
BEGIN
    SET NOCOUNT ON;
    DELETE
    FROM dbo.B
    FROM dbo.B b
        INNER JOIN deleted d ON b.i = d.i
    INSERT INTO dbo.B (i, d, rowdate)
    SELECT i.i
        , i.d
        , i.rowdate
    FROM inserted i;
END
GO

এখানে, আমরা "A" তে 1,000,000 সারি সন্নিবেশ করিয়েছি এবং ট্রিগারটির কারণে, এই সারিগুলি "বি" তেও সন্নিবেশ করা হবে।

;WITH src AS (
    SELECT i.n
    FROM (VALUES (0), (1), (2), (3), (4), (5), (6), (7), (8), (9))i(n)
)
INSERT INTO dbo.A (d, rowdate)
SELECT d = CRYPT_GEN_RANDOM(300), DATEADD(SECOND, s6.n + (s5.n * 100000) + (s4.n * 10000) + (s3.n * 1000) + (s2.n * 100) + (s1.n * 10), '2017-01-01T00:00:00.000')
FROM src s1
    CROSS JOIN src s2
    CROSS JOIN src s3
    CROSS JOIN src s4
    CROSS JOIN src s5
    CROSS JOIN src s6;

ঘরছাড়া হয়ে যাওয়া এড়াতে লেনদেনের লগ সাফ করুন। এটি উত্পাদনে চালাবেন না কারণ এটি "NUL" ডিভাইসে লেনদেনের লগ ডেটা প্রেরণ করে।

BACKUP LOG SwitchTest TO DISK = 'NUL:';
GO

এই সারণিটি সারণি স্থানান্তরিত করার সময় ক্ষতিগ্রস্থ টেবিলগুলির কোনওটিতেই লেখা যায় না তা নিশ্চিত করার জন্য এই কোডটি একটি লেনদেন তৈরি করে:

BEGIN TRANSACTION
EXEC sys.sp_getapplock @Resource = N'TableSwitcher', @LockMode = 'Exclusive', @LockOwner = 'Transaction', @LockTimeout = '1000', @DbPrincipal = N'dbo';
BEGIN TRY
    -- create a table to hold the rows we want to keep
    CREATE TABLE dbo.C
    (
        i int NOT NULL 
            CONSTRAINT PK_C
            PRIMARY KEY CLUSTERED
        , d varchar(300) NOT NULL
        , rowdate datetime NOT NULL
    ) ON [PRIMARY]
    WITH (DATA_COMPRESSION = PAGE);

    --copy the rows we want to keep into "C"
    INSERT INTO dbo.C (i, d, rowdate)
    SELECT b.i
        , b.d
        , b.rowdate
    FROM dbo.B
    WHERE b.rowdate >= '2017-01-11T10:00:00';

    --truncate the entire "B" table
    TRUNCATE TABLE dbo.B;

    --"switch" table "C" into "B"
    ALTER TABLE dbo.C SWITCH TO dbo.B;

    --drop table "C", since we no longer need it
    DROP TABLE dbo.C;

    --shows the count of rows in "B" which were retained.
    SELECT COUNT(1)
    FROM dbo.B
    WHERE b.rowdate >= '2017-01-11T10:00:00';

   --look for rows in "B" that should no longer exist.
    SELECT COUNT(1)
    FROM dbo.B
    WHERE b.rowdate < '2017-01-11T10:00:00';

    --release the applock and commit the transaction
    EXEC sys.sp_releaseapplock @Resource = N'TableSwitcher', @LockOwner = 'Transaction', @DbPrincipal = N'dbo';
    COMMIT TRANSACTION;
END TRY
BEGIN CATCH
    DECLARE @message nvarchar(1000) = ERROR_MESSAGE();
    DECLARE @severity int = ERROR_SEVERITY();
    DECLARE @state int = ERROR_STATE();
    RAISERROR (@message, @severity, @state);
    EXEC sys.sp_releaseapplock @Resource = N'TableSwitcher', @LockOwner = 'Transaction', @DbPrincipal = N'dbo';
    ROLLBACK TRANSACTION;
END CATCH
GO

sp_getapplockএবং sp_releaseapplockএই কোড একই সময়ে চলমান একাধিক দৃষ্টান্ত প্রতিরোধ। আপনি যদি এই কোডটি কোনও জিইউআইয়ের মাধ্যমে পুনরায় ব্যবহার করতে সক্ষম হন তবে এটি সহায়ক হবে।

(নোট করুন যে উত্স অ্যাক্সেসের প্রতিটি প্রক্রিয়া যদি একই ম্যানুয়াল রিসোর্স লকিং যুক্তিকে সুস্পষ্টভাবে প্রয়োগ করে তবে অ্যাপ্লিকেশনগুলির লকগুলি কার্যকর হবে - এসকিউএল সার্ভারের সময় সারণি, পৃষ্ঠাগুলি স্বয়ংক্রিয়ভাবে সারণি, পৃষ্ঠাগুলি লক করে দেয় এমন কোনও যাদু নেই) সন্নিবেশ / আপডেট অপারেশন।)

ট্রিগার দ্বারা "বি" তে inোকানো হয়েছে তা নিশ্চিত করার জন্য, এখন "A" তে সারি সন্নিবেশ করার প্রক্রিয়াটি আমরা পরীক্ষা করি।

INSERT INTO dbo.A (d, rowdate)
VALUES ('testRow', GETDATE());

SELECT *
FROM dbo.B
WHERE B.d = 'testRow'
+ + --------- + + --------- + + ------------------------- + +
| i | ডি | সারিবদ্ধ |
+ + --------- + + --------- + + ------------------------- + +
| 1000001 | পরীক্ষাআর | 2018-04-13 03: 49: 53.343 |
+ + --------- + + --------- + + ------------------------- + +
আমাদের সাইট ব্যবহার করে, আপনি স্বীকার করেছেন যে আপনি আমাদের কুকি নীতি এবং গোপনীয়তা নীতিটি পড়েছেন এবং বুঝতে পেরেছেন ।
Licensed under cc by-sa 3.0 with attribution required.