InnoDB ডিলিট পারফরম্যান্স কিভাবে উন্নত করবেন?


9

সুতরাং আমার এই অডিট টেবিলটি রয়েছে (আমার ডাটাবেসের কোনও টেবিলের ক্রিয়াকলাপগুলি ট্র্যাক করে):

CREATE TABLE `track_table` (
  `id` int(16) unsigned NOT NULL,
  `userID` smallint(16) unsigned NOT NULL,
  `tableName` varchar(255) NOT NULL DEFAULT '',
  `tupleID` int(16) unsigned NOT NULL,
  `date_insert` datetime NOT NULL,
  `action` char(12) NOT NULL DEFAULT '',
  `className` varchar(255) NOT NULL,
  PRIMARY KEY (`id`),
  KEY `userID` (`userID`),
  KEY `tableID` (`tableName`,`tupleID`,`date_insert`),
  KEY `actionDate` (`action`,`date_insert`)
) ENGINE=InnoDB DEFAULT CHARSET=latin1

এবং আমার পুরানো আইটেম সংরক্ষণাগার শুরু করা দরকার। টেবিলটি প্রায় 50 মিলিয়ন সারিতে বেড়েছে, তাই আমি সারিগুলি সরিয়ে ফেলতে দ্রুততম উপায়টি ছিল এটি একবারে একটি ছক মুছে ফেলা (উপর ভিত্তি করে tableName)।

এটি বেশ ভাল কাজ করে তবে কয়েকটি টেবিলের উপর যেগুলি ভারী লেখা রয়েছে, এটি সম্পূর্ণ হবে না। আমার জিজ্ঞাসাটি এমন সমস্ত আইটেম মুছে ফেলে যার সাথে deleteটিপলআইডি / টেবিলনাম সংমিশ্রণের সাথে সম্পর্কিত ক্রিয়া রয়েছে:

DELETE FROM track_table WHERE tableName='someTable' AND tupleID IN (
  SELECT DISTINCT tupleID FROM track_table
  WHERE tableName='someTable' AND action='DELETE' AND date_insert < DATE_SUB(CURDATE(), INTERVAL 30 day)
)

আমি এটিকে আমার সার্ভারে 3 দিনের জন্য চালাতে দিয়েছি এবং এটি বৃহত্তম টেবিলে কখনও শেষ হয়নি। ব্যাখ্যা আউটপুট (যদি আমি নির্বাচন করতে মুছুন স্যুইচ করুন:

| id | select_type        | table       | type | possible_keys      | key     | key_len | ref        | rows    | Extra                        |
|  1 | PRIMARY            | track_table | ref  | tableID            | tableID | 257     | const      | 3941832 | Using where                  |
|  2 | DEPENDENT SUBQUERY | track_table | ref  | tableID,actionDate | tableID | 261     | const,func |       1 | Using where; Using temporary |

সুতরাং 4 মিলিয়ন সারিগুলি মুছতে 3 দিন লাগবে না, আমি ভাবব। আমার আমার ইনডোডবি_বাফলার_পুল_সাইজটি 3 জি-তে সেট করা আছে এবং সার্ভারটি ওয়ান_ফাই_পার_সামগ্রী ব্যবহারের জন্য সেট করা নেই। InnoDB মুছে ফেলতে পারফরম্যান্সের আরও কী কী উপায়ে উন্নতি করতে পারি? (ম্যাক ওএসএক্সে মাইএসকিউএল 5.1.43 চলছে)

উত্তর:


11

আপনি ব্যাচগুলিতে ডেটা মুছতে পারেন।

এসকিউএল সার্ভারে সিনট্যাক্সটি delete top Xএকটি সারণী থেকে সারি। তারপরে আপনি এটি প্রতিটি ব্যাচের জন্য লেনদেনের সাথে একটি লুপে করেন (অবশ্যই যদি আপনার একাধিক বক্তব্য থাকে তবে অবশ্যই) যাতে লেনদেন সংক্ষিপ্ত রাখে এবং কেবলমাত্র স্বল্প সময়ের জন্য লকগুলি বজায় রাখে।

মাইএসকিউএল সিনট্যাক্সে: DELETE FROM userTable LIMIT 1000

এতে বিধিনিষেধ রয়েছে ( LIMITউদাহরণস্বরূপ, যোগদানের সাথে মুছে ফেলাতে ব্যবহার করতে পারবেন না ) তবে এই ক্ষেত্রে আপনি এটি সেভাবে করতে সক্ষম হবেন।

সেখানে ব্যবহার করে একটি অতিরিক্ত বিপদ LIMITসঙ্গে DELETEযখন এটি রেপ্লিকেশন আসে; মুছে ফেলা সারিগুলি মাঝেমধ্যে দাসের একই ক্রমে মুছে ফেলা হয় না কারণ এটি মাস্টারে মুছে ফেলা হয়েছিল।


6

একটি টেম্প টেবিল পদ্ধতির ব্যবহার করে দেখুন। এরকম কিছু চেষ্টা করুন:

ধাপ 1) CREATE TABLE track_table_new LIKE track_table;

ধাপ ২) INSERT INTO track_table_new SELECT * FROM track_table WHERE action='DELETE' AND date_insert >= DATE_SUB(CURDATE(), INTERVAL 30 day);

ধাপ 3) ALTER TABLE track_table RENAME track_table_old;

পদক্ষেপ 4) ALTER TABLE track_table_new RENAME track_table;

পদক্ষেপ 5) DROP TABLE track_table_old;

আমি টিপল ক্ষেত্রটি ২ য় ধাপে অন্তর্ভুক্ত করি নি দয়া করে দেখুন এটি পছন্দসই প্রভাব ফেলে কিনা produces এটি যদি আপনি চান তবে আপনি অন্যান্য কারণে টিপল ক্ষেত্রটি ব্যবহার না করে আপনি পুরোপুরি টিপল ক্ষেত্রটি খাঁজতে চাইতে পারেন।


এটি একটি আকর্ষণীয় সমাধান। আমার টেবিলে টিপল ক্ষেত্র দরকার। টেবিলনাম / টিপলআইডি লগ হওয়া সারণীর একটি অপরিজ্ঞাত বিদেশী কী। অপরিবর্তিত কারণ সম্প্রতি অবধি, এই টেবিলটি মাইআইএসএএম ছিল, যা বিদেশী কী সমর্থন করে না।
ডেরেক ডোনয়

1

ব্যাচে অযাচিত সারিগুলি মোছার সাথে অন্যান্য ক্রিয়াকলাপকে কার্যক্ষম রাখা উচিত। তবে আপনার অপারেশন মোছার শর্ত রয়েছে তাই শর্তাবলীতে কলামগুলিতে উপযুক্ত সূচক রয়েছে কিনা তা নিশ্চিত হয়ে নিন।

যেহেতু মাইএসকিউএল আলগা সূচক স্ক্যানের সম্পূর্ণ ফাংশন সমর্থন করে না, আপনি এর ক্রমটি সামঞ্জস্য করার চেষ্টা করতে KEY actionDate (action, date_insert)পারেন KEY actionDate (date_insert, action)। 'ডেট_ইনসেট' উপসর্গের সাথে, মাইএসকিউএলকে আপনার ডেটটাইম শর্তের পূর্ববর্তী সারিগুলি স্ক্যান করতে এই সূচকটি ব্যবহার করা উচিত।

এই জাতীয় সূচীর সাহায্যে আপনি এসকিউএল লিখতে পারেন:

DELETE
FROM track_table
WHERE tableName='someTable'
    AND action='DELETE'
    AND date_insert < DATE_SUB(CURDATE(), INTERVAL 30 day)
LIMIT 1000 -- Your size of batch

1
| id | select_type        | table       | type | possible_keys      | key     | key_len | ref        | rows    | Extra                        |
|  1 | PRIMARY            | track_table | ref  | tableID            | tableID | 257     | const      | 3941832 | Using where                  |
|  2 | DEPENDENT SUBQUERY | track_table | ref  | tableID,actionDate | tableID | 261     | const,func |       1 | Using where; Using temporary |

-ফিজ, আপনার কী_লেন এত বড় ব্যাখ্যা থেকে> = আপনাকে যতটা সম্ভব ছোট আকারটি ডাউনগ্রেড করতে হবে। আপনার জিজ্ঞাসার জন্য আমি মনে করি সর্বোত্তম উপায় হ'ল ডেটার ধরণের ক্রিয়া ক্ষেত্রের চর (12) থেকে টিনিনেন্টে পরিবর্তন করা, সুতরাং ডেটা ম্যাপিং এর মতো দেখতে:

1: -> DELETE
2: -> UPDATE
3: -> INSERT
...

এবং আপনি টেবিলের পরিবর্তে টেবিল_ইডও পরিবর্তন করতে পারেন। সেরা পারফরম্যান্সের জন্য ডিডিএল করতে পারে:

CREATE TABLE `track_table` (
  `id` int(11) unsigned NOT NULL,
  `userID` smallint(6) unsigned NOT NULL,
  `tableid` smallint(6) UNSIGNED NOT NULL DEFAULT 0,
  `tupleID` int(11) unsigned NOT NULL,
  `date_insert` datetime NOT NULL,
  `actionid` tinyin(4) UNSIGNED NOT NULL DEFAULT 0,
  `className` varchar(255) NOT NULL,
  PRIMARY KEY (`id`),
  KEY `userID` (`userID`),
  KEY `tableID` (`tableid`,`tupleID`,`date_insert`),
  KEY `actionDate` (`actionid`,`date_insert`)
) ENGINE=InnoDB DEFAULT CHARSET=latin1;

CREATE TABLE `actions` (
  `id` tinyint(4) unsigned NOT NULL 
  `actionname` varchar(255) NOT NULL,
  PRIMARY KEY (`id`) 
) ENGINE=InnoDB DEFAULT CHARSET=latin1;

CREATE TABLE `table_name` (
  `id` tinyint(4) unsigned NOT NULL 
  `tablename` varchar(255) NOT NULL,
  PRIMARY KEY (`id`) 
) ENGINE=InnoDB DEFAULT CHARSET=latin1;

সুতরাং কোয়েরিটি দেখতে দেখতে চলতে পারে:

DELETE FROM track_table WHERE tableid=@tblid AND tupleID IN (
  SELECT DISTINCT tupleID FROM track_table
  WHERE tableid=@tblid AND actionid=@actionid AND date_insert < DATE_SUB(CURDATE(), INTERVAL 30 day)
).

তবে দ্রুততম পদ্ধতিটি ছিল পার্টিশন ব্যবহার করা using যাতে আপনি পার্টিশন ড্রপ করতে পারেন। বর্তমানে, আমার টেবিলটি প্রায় 40 মিলির বেশি সারি পেয়েছে। এবং প্রতি ঘন্টা আপডেট করুন (প্রতিটি সময়ের জন্য 400k সারি আপডেট), এবং আমি curr_date পার্টিশনটি ড্রপ করতে এবং টেবিলটিতে ডেটা পুনরায় লোড করতে পারি। ড্রপ কমান্ডটি খুব দ্রুত (<100 মিমি)। এই সাহায্য আশা করি।

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