পোস্টগ্রিসে বিদ্যমান টেবিলটি কীভাবে বিভাজন করবেন?


19

আমি তারিখের সীমা অনুসারে 1M + সারি সহ একটি টেবিল বিভাজন করতে চাই। বেশি ডাউনটাইম বা ডেটা হারাতে ঝুঁকি না নিয়ে কীভাবে সাধারণত এটি করা হয়? আমি বিবেচনা করছি কৌশলগুলি এখানে, কিন্তু পরামর্শের জন্য উন্মুক্ত:

  1. বিদ্যমান সারণী হ'ল মাস্টার এবং শিশুরা এর উত্তরাধিকার সূত্রে প্রাপ্ত। সময়ের সাথে সাথে মাস্টার থেকে শিশুতে ডেটা স্থানান্তরিত করে তবে এমন একটি সময়কালের সময় আসবে যেখানে কিছু ডেটা মাস্টার টেবিলে থাকে এবং কিছু বাচ্চাদের মধ্যে থাকে।

  2. একটি নতুন মাস্টার এবং শিশুদের টেবিল তৈরি করুন। শিশু টেবিলগুলিতে বিদ্যমান সারণীতে ডেটার অনুলিপি তৈরি করুন (সুতরাং ডেটা দুটি জায়গায় থাকবে)। একবার চাইল্ড টেবিলগুলিতে অতি সাম্প্রতিক ডেটা হয়ে গেলে নতুন মাস্টার টেবিলের দিকে নির্দেশ করতে সমস্ত সন্নিবেশ পরিবর্তন করুন এবং বিদ্যমান সারণীটি মুছুন।


1
এখানে আমার ধারণাগুলি: যদি টেবিলগুলিতে ডেটটাইম কলাম থাকে -> নতুন মাস্টার + নতুন শিশু তৈরি করুন -> নতুন + ওল্ডে নতুন ডেটা sertোকান (উদা: তারিখের সময় = 2015-07-06 00:00:00) -> ওল্ড থেকে নতুন বেসে অনুলিপি করুন সময় কলামে (যেখানে: তারিখের সময় <2015-07-06 00:00:00) -> সারণীর নাম পরিবর্তন করুন -> নতুনতে সন্নিবেশ পরিবর্তন করুন -> মাস্টার সন্নিবেশ / আপডেটের জন্য "পার্টিশন ট্রিগার" তৈরি করুন (নতুন ডেটা সন্নিবেশ / আপডেট করুন - > বাচ্চাদের কাছে সরান, তাই শিশুদের মধ্যে নতুন ডেটা inোকানো হবে) -> মাস্টার আপডেট করুন, ট্রিগার ডেটা বাচ্চাদের কাছে সরিয়ে দেবে।
লুয়ান হুইন

@ ইন্হ্নহ, সুতরাং আপনি দ্বিতীয় বিকল্পটির পরামর্শ দিচ্ছেন, তবে তারপরে ডেটা অনুলিপি করা হয়ে গেলে পুরানো টেবিলটি মুছুন এবং পুরানো টেবিলের মতো একই নাম রাখতে নতুন টেবিলটির নামকরণ করুন। এটা কি সঠিক?
ইভান অ্যাপলবি

পুরানো টেবিলের নতুন টেবিলটির নতুন নামকরণ করুন, তবে নতুন প্রবাহের পার্টিশন টেবিলগুলি পুরোপুরি ঠিক না হওয়া পর্যন্ত আপনার পুরানো টেবিলটি রাখা উচিত।
লুয়ান হুইন

2
মাত্র কয়েক মিলিয়ন সারিগুলির জন্য আমি ভাবি না যে বিভাজনটি আসলে প্রয়োজনীয়। আপনি কেন এটি প্রয়োজন বলে মনে করেন? আপনি কোন সমস্যার সমাধান করার চেষ্টা করছেন?
a_horse_with_no_name

1
@EvanAppleby DELETE FROM ONLY master_tableসমাধান।
dezso

উত্তর:


21

যেহেতু # 1 টি সক্রিয় উত্পাদনের পরিবেশে থাকা অবস্থায় মাস্টার থেকে ডেটা অনুলিপি করা প্রয়োজন, তাই আমি ব্যক্তিগতভাবে # 2 দিয়েছি (একটি নতুন মাস্টার তৈরি করা)। এটি সক্রিয়ভাবে ব্যবহারের সময় মূল টেবিলটিতে বাধা রোধ করে এবং যদি কোনও সমস্যা থাকে তবে আমি সহজেই ইস্যু ছাড়াই নতুন মাস্টারটিকে মুছতে এবং মূল টেবিলটি ব্যবহার চালিয়ে যেতে পারি। এটি করার পদক্ষেপ এখানে:

  1. নতুন মাস্টার টেবিল তৈরি করুন।

    CREATE TABLE new_master (
        id          serial,
        counter     integer,
        dt_created  DATE DEFAULT CURRENT_DATE NOT NULL
    );
  2. মাস্টার থেকে উত্তরাধিকার সূত্রে প্রাপ্ত শিশুদের তৈরি করুন।

    CREATE TABLE child_2014 (
        CONSTRAINT pk_2014 PRIMARY KEY (id),
        CONSTRAINT ck_2014 CHECK ( dt_created < DATE '2015-01-01' )
    ) INHERITS (new_master);
    CREATE INDEX idx_2014 ON child_2014 (dt_created);
    
    CREATE TABLE child_2015 (
        CONSTRAINT pk_2015 PRIMARY KEY (id),
        CONSTRAINT ck_2015 CHECK ( dt_created >= DATE '2015-01-01' AND dt_created < DATE '2016-01-01' )
    ) INHERITS (new_master);
    CREATE INDEX idx_2015 ON child_2015 (dt_created);
    
    ...
  3. সমস্ত মাস্টার dataতিহাসিক ডেটা নতুন মাস্টার টেবিলে অনুলিপি করুন

    INSERT INTO child_2014 (id,counter,dt_created)
    SELECT id,counter,dt_created
    from old_master
    where dt_created < '01/01/2015'::date;
  4. অস্থায়ীভাবে নতুন সন্নিবেশ / প্রোডাকশন ডেটাবেজে আপডেট

  5. নতুন মাস্টার সারণীতে সর্বশেষতম ডেটা অনুলিপি করুন

    INSERT INTO child_2015 (id,counter,dt_created)
    SELECT id,counter,dt_created
    from old_master
    where dt_created >= '01/01/2015'::date AND dt_created < '01/01/2016'::date;
  6. টেবিলগুলির নাম পরিবর্তন করুন যাতে new_master উত্পাদন ডাটাবেসে পরিণত হয়।

    ALTER TABLE old_master RENAME TO old_master_backup;
    ALTER TABLE new_master RENAME TO old_master;
  7. পুরানো_মাস্টারে ইনসার্টের বিবৃতিগুলির জন্য ফাংশন যুক্ত করুন যাতে ডেটা পার্টিশনের সঠিক হয়ে যায়।

    CREATE OR REPLACE FUNCTION fn_insert() RETURNS TRIGGER AS $$
    BEGIN
        IF ( NEW.dt_created >= DATE '2015-01-01' AND
             NEW.dt_created < DATE '2016-01-01' ) THEN
            INSERT INTO child_2015 VALUES (NEW.*);
        ELSIF ( NEW.dt_created < DATE '2015-01-01' ) THEN
            INSERT INTO child_2014 VALUES (NEW.*);
        ELSE
            RAISE EXCEPTION 'Date out of range';
        END IF;
        RETURN NULL;
    END;
    $$
    LANGUAGE plpgsql;
  8. ট্রিগার যুক্ত করুন যাতে ফাংশনটি INSERTS এ ডাকা হয়

    CREATE TRIGGER tr_insert BEFORE INSERT ON old_master
    FOR EACH ROW EXECUTE PROCEDURE fn_insert();
  9. সীমাবদ্ধতা বাদ দেওয়া চালু করুন

    SET constraint_exclusion = on;
  10. উত্পাদন ডেটাবেজে UPDATES এবং INSERTS পুনরায় সক্ষম করুন

  11. ট্রিগার বা ক্রোন সেট আপ করুন যাতে নতুন পার্টিশন তৈরি হয় এবং পার্টিশনটি সংশোধন করতে নতুন ডেটা বরাদ্দ করতে ফাংশন আপডেট হয়। কোড উদাহরণের জন্য এই নিবন্ধটি উল্লেখ করুন

  12. পুরানো_মাস্টার_ব্যাকআপ মুছুন


1
ভাল লেখার। এটি যদি আপনার প্রশ্নগুলি আরও দ্রুত করে তোলে তবে এটি আকর্ষণীয় হবে। ১০ মিলিয়ন এখনও অনেকগুলি সারি নয় যা আমি বিভাজন সম্পর্কে চিন্তা করব। আমি অবাক হই যদি আপনার অবনতিশীল পারফরম্যান্স সম্ভবত vacuum"লেনদেনের ক্ষেত্রে নিষ্ক্রিয়" সেশনের কারণে ধরা না পড়ার বা প্রতিরোধের কারণে হয়ে থাকে।
a_horse_with_no_name

@a_horse_with_no_name, এখনও অবধি এটি কোয়েশনগুলি উল্লেখযোগ্যভাবে উন্নত করতে পারেনি :( আমি হিরোকু ব্যবহার করি যার অটো-ভ্যাকুয়াম সেটিংস রয়েছে এবং এটি এই বৃহত টেবিলের জন্য প্রতিদিন ঘটেছিল। এই বিষয়টি আরও ভালভাবে দেখবে
ইভান অ্যাপলবি

পদক্ষেপ 3 এবং 5 এ সন্নিবেশগুলি নতুন_মাস্টার টেবিল করা উচিত নয় এবং পোস্টগ্র্যাস্কলকে সঠিক শিশু টেবিল / পার্টিশনটি বেছে নিতে দেওয়া উচিত?
পাকম্যান

@ পাকম্যান সঠিক শিশুকে নির্ধারিত করার কাজটি ধাপ 7 পর্যন্ত যোগ হবে না
ইভান অ্যাপলবি

4

Pg_pathman ( https://github.com/postgrespro/pg_pathman ) নামে একটি নতুন সরঞ্জাম রয়েছে যা স্বয়ংক্রিয়ভাবে আপনার জন্য এটি করবে।

নীচের মত কিছু এটি করতে হবে।

SELECT create_range_partitions('master', 'dt_created', 
   '2015-01-01'::date, '1 day'::interval);
আমাদের সাইট ব্যবহার করে, আপনি স্বীকার করেছেন যে আপনি আমাদের কুকি নীতি এবং গোপনীয়তা নীতিটি পড়েছেন এবং বুঝতে পেরেছেন ।
Licensed under cc by-sa 3.0 with attribution required.