30,000,000 সারি টেবিলটিতে কমান্ড মুছে ফেলছে না LE


22

আমি একটি ডাটাবেস উত্তরাধিকারসূত্রে পেয়েছি এবং এটি পরিষ্কার এবং দ্রুত করার চেষ্টা করছি। আমার কাছে একটি টেবিল রয়েছে যার মধ্যে 30,000,000 সারি রয়েছে, যার মধ্যে অনেকগুলি আমাদের প্রোগ্রামারটির ত্রুটির কারণে জাঙ্ক ডেটা .োকানো হয়। আমি কোনও নতুন, আরও অনুকূলিতকরণ সূচকগুলি যুক্ত করার আগে, আমি মাইআইএসএএম থেকে টেবিলটি ইনোডিবিতে রূপান্তরিত করেছি এবং জাঙ্ক ডেটা ধারণ করে এমন অনেকগুলি সারি মুছতে চাইছি।

ডাটাবেসটি মাইএসকিউএল 5.0 এবং সার্ভারে আমার রুট অ্যাক্সেস রয়েছে। আমি প্রথমে অ্যাডমিনারের মাধ্যমে এই কমান্ডগুলি চালিয়ে যাচ্ছিলাম এবং তারপরে পিএইচপিএমওয়াই অ্যাডমিন, একই ফলাফল সহ with

আমি যে কমান্ডটি চালাচ্ছি তা হ'ল

DELETE
FROM `tablename`
WHERE `columnname` LIKE '-%'

মূলত, এই কলামে ড্যাশ দিয়ে শুরু হওয়া যে কোনও কিছু মুছুন -

এটি প্রায় 3-5 মিনিটের জন্য চালায় এবং তারপরে আমি যখন প্রক্রিয়া তালিকাটি দেখি, এটি চলে যায়।

আমি তখন দৌড়,

SELECT *
FROM `tablename`
WHERE `columnname` LIKE '-%'

এবং এটি কয়েক মিলিয়ন সারি প্রদান করে।

আমার মোছার বিবৃতিটি কেন সম্পূর্ণ হচ্ছে না?

পিএস, আমি মাইএসকিউএল 5.0 কতটা পুরানো তা সম্পর্কে আমি সচেতন। আমি ডিবিকে মাইএসকিউএল 5.6 ডব্লু ইনোডিবিতে স্থানান্তরিত করতে কাজ করছি (সম্ভবত মারিয়াডবি 10 ডাব্লু এক্সট্রাডিবি) তবে যতক্ষণ না ঘটে ততক্ষণে আমি ডিবি দিয়ে উত্তরটি খুঁজছি।

-

সম্পাদনা সরানো হয়েছে, আমার উত্তর দেখুন।

উত্তর:


24

InnoDB এর আর্কিটেকচারটি দেখুন (পারকোনা সিটিও ভাদিম টাকাচেনকো থেকে চিত্র)

InnoDB নদীর গভীরতানির্ণয়

আপনি যে সারিগুলি মুছে ফেলছেন তা পূর্বাবস্থায় লগগুলিতে লেখা হচ্ছে। মুছার সময়কালের জন্য এখনই আইবডাতা 1 ফাইলটি বাড়ানো উচিত। Mysqlperformanceblog.com এরReasons for run-away main Innodb Tablespace মতে :

  • প্রচুর লেনদেনমূলক পরিবর্তন
  • খুব দীর্ঘ লেনদেন
  • লগিং পুরা থ্রেড

আপনার ক্ষেত্রে, কারণ # 1 আপনি সারিগুলি মোছার কারণে কিছুটা পূর্ববর্তী স্থানের সাথে একটি রোলব্যাক অংশও দখল করবে। মুছে ফেলা শেষ না হওয়া পর্যন্ত এই সারিগুলি অবশ্যই ইবদাটা 1 এ বসতে হবে। সেই স্থানটি যৌক্তিকভাবে বাতিল করা হয়েছে তবে ডিস্কস্পেসটি সঙ্কুচিত হয় না।

আপনার এখনই সেই মুছে ফেলতে হবে। আপনি মুছে ফেলা ক্যোয়ারীটি একবার মেরে ফেললে, এটি মোছা সারিগুলিকে রোলব্যাক করবে।

পরিবর্তে আপনি এটি করুন:

CREATE TABLE tablename_new LIKE tablename;
INSERT INTO tablename_new SELECT * FROM tablename WHERE `columnname` NOT LIKE '-%';
RENAME TABLE
    tablename TO tablename_old,
    tablename_new TO tablename
;
DROP TABLE tablename_old;

আপনি প্রথমে সারণীর মাইআইএসএএম সংস্করণটির বিপরীতে এটি করতে পারতেন। তারপরে, এটি InnoDB এ রূপান্তর করুন।


21

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

আমি জিজ্ঞাসা চালানো mysql ইন্টারেক্টিভ প্রম্পটে চালিয়েছি এবং ত্রুটি বার্তাটি লক্ষ্য করেছি,

mysql> DELETE FROM `slugs` WHERE `slug` LIKE '-%';
ERROR 1206 (HY000): The total number of locks exceeds the lock table size

ত্রুটিটি গুগল করার মাধ্যমে, আমি সমাধানটি ফাইলের innodb_buffer_pool_sizeমাধ্যমে বৃদ্ধি /etc/my.cnfএবং মাইএসকিএল ডিমন পুনরায় বুট করাতে পেলাম । আমার সার্ভারের জন্য এটি ডিফল্টে সেট করা হয়েছিল 8Mএবং আমি এটিকে বাড়িয়েছি1G (সার্ভারটিতে 32 গিগাবাইট রয়েছে এবং এটি কেবলমাত্র টেবিল যা বর্তমানে ইনোডিবি)।

mysql> DELETE FROM `slugs` WHERE `slug` LIKE '-%';
Query OK, 23517226 rows affected (27 min 33.23 sec)

তারপরে আমি কমান্ডটি চালাতে এবং ২~ মিনিটের মধ্যে ২৩ মিলিয়ন রেকর্ড মুছতে সক্ষম হয়েছি।

কী কী innodb_buffer_pool_sizeসেট করতে হবে সেই কৌতূহলীদের জন্য আপনার কতটা র‌্যাম রয়েছে তা নোট করুন এবং তারপরে এই থ্রেডটি দেখুন যা জিবিতে প্রস্তাবিত অনুমান দেয়।


12

রোল্যান্ডের পরামর্শটি দুটি জিনিস একসাথে করে কিছুটা বাড়িয়ে দেওয়া যেতে পারে:

CREATE TABLE tablename_new LIKE tablename;
ALTER TABLE tablename_new ENGINE = InnoDB;
INSERT INTO tablename_new 
    SELECT * FROM tablename WHERE `columnname` NOT LIKE '-%' ORDER BY primary_key;
RENAME TABLE
    tablename TO tablename_old,
    tablename_new TO tablename
;
DROP TABLE tablename_old;

তবে এখানে এমন একটি ব্লগ রয়েছে যা আপাতদৃষ্টিতে চিরকালের জন্য গ্রহণের চেয়ে খণ্ডগুলিতে কীভাবে বড় ডিলেটগুলি করবেন তা ব্যাখ্যা করে: http://mysql.rjweb.org/doc.php/deletebig পিকে-র মাধ্যমে টেবিলের মধ্যে দিয়ে 1K করে যেতে হবে একবারে সারি। (অবশ্যই সচেতন হওয়ার জন্য আরও বিশদ রয়েছে))

এবং এই ব্লগটি ইনোডিবিতে রূপান্তরকালে সম্ভাব্য গোটাচাকে সম্বোধন করেছে: http://mysql.rjweb.org/doc.php/myisam2innodb


5

আমার প্রথম প্রবৃত্তিটি একাধিক বার করা হবে, কোয়েরি ফলাফলের সংখ্যা সীমাবদ্ধ করে এবং একাধিকবার কোয়েরি চালানো:

DELETE
FROM `tablename`
WHERE `columnname` LIKE '-%' LIMIT 1000000

এই পদ্ধতির একটি অপূর্ণতা: প্রতিটি মুছতে আরও বেশি সময় লাগবে। এর কারণ এটি আরও বেশি সারি ছাড়তে হবে যা এর সাথে মেলে না WHERE
রিক জেমস

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

বৈধ বিন্দু. (আমি LIMITনিম্নতর করব; 10000 বলুন))
রিক জেমস

4

সবচেয়ে সহজ সমাধানটি কেবল এটি না করা - একটি ছোট মুছুন, যা আরও সহজে প্রক্রিয়া করা যায়।

এই ক্ষেত্রে আমি ফর্মটির ক্রমিক মুছে ফেলার চেষ্টা করার পরামর্শ দিয়েছি:

DELETE
FROM `tablename`
WHERE `columnname` LIKE '-a%'

2

হতে পারে আপনি এরকম কিছু করতে পারেন:

  • নামে পরিচিত একটি নতুন ক্ষেত্র যুক্ত করুন deleted
  • মত একটি আপডেট করুন UPDATE tablename SET deleted=1 WHERE `columnname` LIKE '-a%'
  • cronরাতের সময় এটি মুছে ফেলতে সেট করুন ।

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