ওরাকলে খুব বড় রেকর্ডসেট মোছার সেরা উপায়


18

আমি একটি অ্যাপ্লিকেশন পরিচালনা করি যা খুব বড় (এক টেবিলের 500 মিলিয়নেরও বেশি সারি সহ প্রায় 1TB ডেটা) ওরাকল ডাটাবেস ব্যাক এন্ড থাকে। ডাটাবেসটি সত্যিই কিছু করে না (কোনও এসপ্রোকস, কোনও ট্রিগার বা কিছু নেই) এটি কেবল একটি ডেটা স্টোর।

প্রতি মাসে আমাদের প্রধান টেবিল দুটি থেকে রেকর্ড মুছে ফেলা প্রয়োজন। শুদ্ধির মানদণ্ডটি পরিবর্তিত হয় এবং এটি সারি বয়সের এবং কয়েকটি স্থিতির ক্ষেত্রের সংমিশ্রণ। আমরা সাধারণত মাসে 10 থেকে 50 মিলিয়ন সারিগুলির মধ্যে শুদ্ধি শেষ করি (আমরা আমদানির মাধ্যমে সপ্তাহে প্রায় 3-5 মিলিয়ন সারি যোগ করি)।

বর্তমানে আমাদের প্রায় 50,000 সারির ব্যাচগুলিতে এই মুছাটি করতে হবে (উদাঃ 50000, কমিট, 50000 মুছুন, প্রতিশ্রুতি দিন, পুনরাবৃত্তি করুন)। পুরো ব্যাচটি একবারে মুছে ফেলার চেষ্টা করা ডাটাবেসটিকে প্রায় এক ঘন্টার জন্য উত্তর দেয় না (সারিগুলির # টির উপর নির্ভর করে)। এই জাতীয় ব্যাচগুলিতে সারিগুলি মুছে ফেলা আমাদের সিস্টেমে খুব রুক্ষ এবং আমরা সাধারণত "সপ্তাহের অনুমতি অনুসারে" এক সপ্তাহের মধ্যে এটি করতে হয়; স্ক্রিপ্টটি অবিচ্ছিন্নভাবে চালিত হতে দেওয়ার ফলে কর্মক্ষমতা হ্রাস পেতে পারে যা ব্যবহারকারীর কাছে অগ্রহণযোগ্য।

আমি বিশ্বাস করি যে এই ধরণের ব্যাচ মুছে ফেলা সূচি কার্যকারিতাও হ্রাস করে এবং অন্যান্য প্রভাব রয়েছে যা শেষ পর্যন্ত ডাটাবেসের কর্মক্ষমতা হ্রাস করতে পারে। কেবলমাত্র একটি টেবিলে 34 টি সূচী রয়েছে এবং সূচী ডেটা আকারটি কেবল ডেটা থেকে বেশি।

আমাদের আইটি লোকের একজন এই শুদ্ধি করতে ব্যবহৃত স্ক্রিপ্টটি এখানে:

BEGIN
LOOP

delete FROM tbl_raw 
  where dist_event_date < to_date('[date]','mm/dd/yyyy') and rownum < 50000;

  exit when SQL%rowcount < 49999;

  commit;

END LOOP;

commit;

END;

এই ডাটাবেসটি অবশ্যই 99.99999% এর উপরে থাকতে হবে এবং আমরা বছরে একবার মাত্র 2 দিনের রক্ষণাবেক্ষণ উইন্ডো পেয়েছি।

আমি এই রেকর্ডগুলি অপসারণের জন্য আরও ভাল পদ্ধতির সন্ধান করছি, তবে এখনও আমি এর কোনও সন্ধান করতে পারি নি। কোনও পরামর্শ?


এছাড়াও খেয়াল করুন এখানে খেলতে 30+ সূচী রয়েছে
jcolebrand

উত্তর:


17

'এ' এবং 'বি' যুক্ত যুক্তিটি কোনও ভার্চুয়াল কলামের পিছনে "লুকানো" থাকতে পারে যার উপর আপনি বিভাজন করতে পারেন:

alter session set nls_date_format = 'yyyy-mm-dd';
drop   table tq84_partitioned_table;

create table tq84_partitioned_table (
  status varchar2(1)          not null check (status in ('A', 'B')),
  date_a          date        not null,
  date_b          date        not null,
  date_too_old    date as
                       (  case status
                                 when 'A' then add_months(date_a, -7*12)
                                 when 'B' then            date_b
                                 end
                        ) virtual,
  data            varchar2(100) 
)
partition   by range  (date_too_old) 
( 
  partition p_before_2000_10 values less than (date '2000-10-01'),
  partition p_before_2000_11 values less than (date '2000-11-01'),
  partition p_before_2000_12 values less than (date '2000-12-01'),
  --
  partition p_before_2001_01 values less than (date '2001-01-01'),
  partition p_before_2001_02 values less than (date '2001-02-01'),
  partition p_before_2001_03 values less than (date '2001-03-01'),
  partition p_before_2001_04 values less than (date '2001-04-01'),
  partition p_before_2001_05 values less than (date '2001-05-01'),
  partition p_before_2001_06 values less than (date '2001-06-01'),
  -- and so on and so forth..
  partition p_ values less than (maxvalue)
);

insert into tq84_partitioned_table (status, date_a, date_b, data) values 
('B', date '2008-04-14', date '2000-05-17', 
 'B and 2000-05-17 is older than 10 yrs, must be deleted');


insert into tq84_partitioned_table (status, date_a, date_b, data) values 
('B', date '1999-09-19', date '2004-02-12', 
 'B and 2004-02-12 is younger than 10 yrs, must be kept');


insert into tq84_partitioned_table (status, date_a, date_b, data) values 
('A', date '2000-06-16', date '2010-01-01', 
 'A and 2000-06-16 is older than 3 yrs, must be deleted');


insert into tq84_partitioned_table (status, date_a, date_b, data) values 
('A', date '2009-06-09', date '1999-08-28', 
 'A and 2009-06-09 is younger than 3 yrs, must be kept');

select * from tq84_partitioned_table order by date_too_old;

-- drop partitions older than 10 or 3 years, respectively:

alter table tq84_partitioned_table drop partition p_before_2000_10;
alter table tq84_partitioned_table drop partition p_before_2000_11;
alter table tq84_partitioned_table drop partition p2000_12;

select * from tq84_partitioned_table order by date_too_old;

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

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

14

এর সর্বোত্তম সমাধানটি হ'ল আপনার টেবিলগুলি বিভাজন করা , যেমন মাসে বা সপ্তাহে। আপনি যদি এগুলি আগে না এসে থাকেন তবে একটি বিভাজনযুক্ত টেবিলটি বেশ কয়েকটি অনুরূপ কাঠামোগত টেবিলের মতো যা UNIONনির্বাচন করার সময় অন্তর্নিহিত থাকে এবং অরাকল পার্টিশনের মানদণ্ডের ভিত্তিতে এটি সন্নিবেশ করানোর সময় স্বয়ংক্রিয়ভাবে উপযুক্ত পার্টিশনে একটি সারি সঞ্চয় করবে। আপনি সূচকগুলি উল্লেখ করেছেন - ভাল প্রতিটি পার্টিশনের নিজস্ব বিভাজনযুক্ত সূচকগুলিও পাওয়া যায়। পার্টিশনটি ফেলে দেওয়ার জন্য এটি ওরাকলে খুব সস্তা অপারেশন (এটি a এর সাথে সাদৃশ্যপূর্ণ)TRUNCATEলোডের ক্ষেত্রে কারণ এটি আপনি যা করছেন তা হ'ল - এই অদৃশ্য সাব-টেবিলগুলির একটি ছাঁটাই বা বাদ দেওয়া)। এটি "সত্যের পরে" বিভাজনে প্রক্রিয়াজাতকরণের একটি উল্লেখযোগ্য পরিমাণ হবে, তবে ছড়িয়ে পড়া দুধের জন্য কাঁদতে কোনও বুদ্ধি নেই - এতদূর করার ব্যয়গুলি ছাড়িয়ে যাওয়ার সুবিধা। প্রতি মাসে আপনি উপরের পার্টিশনটি বিভক্ত করে পরবর্তী মাসের ডেটার জন্য একটি নতুন পার্টিশন তৈরি করবেন (আপনি সহজেই এটিকে একটি এর মাধ্যমে স্বয়ংক্রিয় করতে পারেন DBMS_JOB)।

এবং পার্টিশনগুলির সাহায্যে আপনি সমান্তরাল ক্যোয়ারী এবং পার্টিশন নির্মূলকরণও কাজে লাগাতে পারেন , যা আপনার ব্যবহারকারীদের খুব আনন্দিত করা উচিত ...


এফডব্লিউআইডাব্লু আমরা এই সাইটে 30Tb + ডাটাবেসে আমার সাইটে এই কৌশলটি ব্যবহার করি
গাইস

বিভাজনে সমস্যাটি হ'ল ডেটা বিভাজন করার কোনও সুস্পষ্ট কাটা উপায় নেই। দুটি সারণীর একটিতে (নীচে দেখানো একটি নয়) শুদ্ধ করার জন্য ব্যবহৃত মানদণ্ড দুটি পৃথক (এবং স্বতন্ত্র) তারিখ ক্ষেত্র এবং একটি স্থিতি ক্ষেত্রের উপর ভিত্তি করে। উদাহরণস্বরূপ, যদি স্ট্যাটাসটি 3 বছরের বেশি হয় Aতবে DateAতা শুদ্ধ হয়ে যায়। যদি স্ট্যাটাসটি 10 বছরেরও বেশি হয় Bএবং DateBতা পুরানো হয়। পার্টিশন সম্পর্কে আমার বোঝা যদি সঠিক হয়, তবে বিভাজনটি এই জাতীয় পরিস্থিতিতে (অন্ততপক্ষে শুদ্ধিকরণের বিষয়টি হিসাবে) কার্যকর হবে না।
কোডিং গরিলা

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

6
বিকল্পভাবে আপনি একটি ভার্চুয়াল কলাম তৈরি করতে পারেন যা স্থিতিটি A এবং তারিখবি যখন স্থিতি B হয় এবং তারপরে ভার্চুয়াল কলামে বিভাগ হয় Date একই পার্টিশন মাইগ্রেশন ঘটতে পারে, তবে এটি আপনার শুদ্ধকরণে সহায়তা করবে। দেখে মনে হচ্ছে এটি উত্তর হিসাবে ইতিমধ্যে পোস্ট করা হয়েছিল।
লেইফ রিফেল

4

একটি দিক বিবেচনা করার বিষয় হ'ল সূচিগুলি থেকে মুছে দেওয়া পারফরম্যান্সের ফলাফল কত এবং কাঁচা টেবিল থেকে কতটা। সারণী থেকে মুছে ফেলা প্রতিটি রেকর্ড প্রতিটি বিটি সূচক থেকে সারি একই মুছে ফেলা প্রয়োজন। যদি আপনি 30+ বিটিআর সূচি পেয়ে থাকেন তবে আমার সন্দেহ হয় আপনার বেশিরভাগ সময় সূচি রক্ষণাবেক্ষণে ব্যয় করা হয়।

এটি বিভাজনটির দরকারীতার উপর প্রভাব ফেলে। বলুন আপনার নামের উপর একটি সূচক রয়েছে। একটি স্ট্যান্ডার্ড বিট্রি সূচক, সমস্ত এক বিভাগে, মূল ব্লক থেকে পাতার ব্লকের দিকে যেতে এবং চারটি পর্ব সারি পেতে পঞ্চম পড়তে হতে পারে। যদি সেই সূচকটি 50 টি বিভাগে বিভক্ত হয়ে যায় এবং কোয়েরির অংশ হিসাবে আপনার কাছে পার্টিশন কী না থাকে, তবে এই 50 টি বিভাগের প্রত্যেকটির চেক করা দরকার। প্রতিটি বিভাগটি আরও ছোট হবে, সুতরাং আপনাকে কেবল ২ টি জাম্প করতে হতে পারে তবে আপনি এখনও আগের 5 এর চেয়ে 100 টি পঠন শেষ করতে পারেন।

যদি সেগুলি বিটম্যাপ সূচক হয় তবে সমীকরণগুলি পৃথক। আপনি পৃথক সারিগুলি সনাক্ত করতে সম্ভবত সূচকগুলি ব্যবহার করছেন না, বরং সেগুলির সেটগুলি তৈরি করছেন। সুতরাং কোনও একক রেকর্ডকে ফেরত দিতে 5 আইও ব্যবহার করে কোনও প্রশ্নের চেয়ে এটি 10,000 টি আইও ব্যবহার করছে। যেমন সূচকের অতিরিক্ত পার্টিশনে অতিরিক্ত ওভারহেড কোনও ব্যাপার নয়।


2

50,000 ব্যাচে প্রতি মাসে 50 মিলিয়ন রেকর্ড মুছে ফেলা কেবল 1000 পুনরাবৃত্তি। আপনি যদি প্রতি 30 মিনিটে 1 মুছুন তবে এটি আপনার প্রয়োজনীয়তা পূরণ করবে। আপনার পোস্ট করা ক্যোয়ারী চালানোর জন্য একটি নির্ধারিত টাস্ক কিন্তু লুপটি সরিয়ে ফেলুন এটি কেবল একবার কার্যকর হলে ব্যবহারকারীদের কাছে লক্ষণীয় অবক্ষয়ের কারণ হবে না। আমরা আমাদের উত্পাদন কেন্দ্রটিতে রেকর্ডগুলির একই পরিমাণ সম্পর্কে প্রায় 24/7 চলমান এবং এটি আমাদের চাহিদা পূরণ করে। আমরা প্রতি 10 মিনিটে এটি আরও 10,000 টি রেকর্ড ছড়িয়ে দিয়েছি, যা আমাদের ওরাকল ইউনিক্স সার্ভারগুলিতে প্রায় 1 বা 2 সেকেন্ডে চালিত হয়।


বিশাল 'পূর্বাবস্থা' এবং 'পুনরায়' 'মুছুন' উত্পন্ন করবে কি? এটি আইওকেও দমন করে ... 'মুছুন' ভিত্তিক পদ্ধতির অবশ্যই অবশ্যই কোনও বড় .. বড় টেবিলের জন্য কোনও নয়।
পাহাড়ায়োগি

1

যদি ডিস্কের স্থানটি প্রিমিয়ামে না থাকে, আপনি টেবিলের একটি "কাজের" অনুলিপি তৈরি করতে সক্ষম হবেন, বলুন my_table_new, সিটিএএস ব্যবহার করুন (নির্বাচন করুন সারণী নির্বাচন করুন) এমন মানদণ্ড যা বাদ দেওয়া রেকর্ডগুলি বাদ দিতে পারে। আপনি ক্রিয়েট স্টেটমেন্টটি সমান্তরালভাবে করতে এবং এটি দ্রুত করার জন্য সংযোজন ইঙ্গিতটি দিয়ে করতে পারেন এবং তারপরে আপনার সমস্ত সূচী তৈরি করতে পারেন। তারপরে, এটি শেষ হয়ে গেলে, (এবং পরীক্ষিত), বিদ্যমান টেবিলটির নতুন my_table_oldনামকরণ করুন এবং "ওয়ার্ক" টেবিলটির নতুন নামকরণ করুন my_table। একবার আপনি drop my_table_old purgeপুরানো টেবিলটি থেকে মুক্তি পেতে সমস্ত কিছুতে স্বাচ্ছন্দ্য বোধ করেন । যদি বিদেশের কী সংযমগুলির একটি গুচ্ছ থাকে তবে dbms_redefinition পিএল / এসকিউএল প্যাকেজটি একবার দেখুন । উপযুক্ত বিকল্পগুলি ব্যবহার করার সময় এটি আপনার সূচকগুলি, সীমাবদ্ধতাগুলি ইত্যাদি ক্লোন করে দেবে। এটি অ্যাসটম-এর টম কিয়েটের একটি পরামর্শের সংমিশ্রণখ্যাতি। প্রথম দৌড়ের পরে, আপনি সমস্ত কিছু স্বয়ংক্রিয় করতে পারেন, এবং তৈরি টেবিলটি আরও দ্রুত হওয়া উচিত, এবং সিস্টেমটি চলাকালীন শেষ করা যেতে পারে, এবং অ্যাপ্লিকেশন ডাউনটাইমটি টেবিলগুলির নাম পরিবর্তন করতে এক মিনিটেরও কম সীমাবদ্ধ থাকবে। বেশ কয়েকটি ব্যাচ মুছে ফেলার চেয়ে সিটিএএস ব্যবহার করা আরও দ্রুত হবে। আপনার কাছে পার্টিশন লাইসেন্সবিহীন না থাকলে এই পদ্ধতিটি বিশেষভাবে কার্যকর হতে পারে।

নমুনা সিটিএএস, সর্বশেষ ৩5৫ দিনের ডেটা সহ সারি রাখছে এবং flag_inactive = 'N':

create /*+ append */ table my_table_new 
   tablespace data as
   select /*+ parallel */ * from my_table 
       where some_date >= sysdate -365 
       and flag_inactive = 'N';

-- test out my_table_new. then if all is well:

alter table my_table rename to my_table_old;
alter table my_table_new rename to my_table;
-- test some more
drop table my_table_old purge;

1
এটি বিবেচনা করা যেতে পারে যদি (ক) শুদ্ধি করা একটি একক কাজ হয়। (খ) আপনার যদি কম সারি ধরে রাখতে হয় এবং বেশিরভাগ ডেটা অপসারণ করা হয় ...
পাহাড়ায়োগি

0

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

"আমরা সাধারণত মাসে 10 থেকে 50 মিলিয়ন সারিগুলির মধ্যে শুদ্ধি শেষ করি"

আমি পিএল / এসকিউএল ব্যাচটি মুছতে ব্যবহার করার পরামর্শ দেব, বেশ কয়েক ঘন্টা ঠিক আছে বলে মনে করি।


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

@ গ্যান্ডল্ফ ৯৮৯ একটি পার্টিশনটি বাদ দিয়ে সর্বদা একটি বৈশ্বিক সূচককে ব্যবহারযোগ্য না করে
অলৌকিক কাজ ১73৩ মে'১16
আমাদের সাইট ব্যবহার করে, আপনি স্বীকার করেছেন যে আপনি আমাদের কুকি নীতি এবং গোপনীয়তা নীতিটি পড়েছেন এবং বুঝতে পেরেছেন ।
Licensed under cc by-sa 3.0 with attribution required.