داستان حذف فیزیکی 300 میلیون رکورد در MySQL

معرفی

سلام. من ningenMe هستم، توسعه دهنده وب.

همانطور که عنوان می گوید، داستان من داستان حذف فیزیکی 300 میلیون رکورد در MySQL است.

من به این علاقه مند شدم، بنابراین تصمیم گرفتم یک یادآوری (دستورالعمل) ایجاد کنم.

صفحه اصلی - هشدار

سرور دسته‌ای که من استفاده می‌کنم و نگهداری می‌کنم یک فرآیند منظم دارد که داده‌های ماه گذشته را یک بار در روز از MySQL جمع‌آوری می‌کند.

معمولاً این فرآیند در حدود 1 ساعت تکمیل می شود، اما این بار برای 7 یا 8 ساعت کامل نشد و هشدار متوقف نشد...

جستجوی دلیل

من سعی کردم روند را دوباره راه اندازی کنم و به گزارش ها نگاه کنم، اما مشکلی ندیدم.
پرس و جو به درستی ایندکس شد. اما زمانی که به اشتباه فکر کردم، متوجه شدم که اندازه پایگاه داده بسیار بزرگ است.

hoge_table | 350'000'000 |

350 میلیون رکورد به نظر می رسید که نمایه سازی درست کار می کند، فقط بسیار کند است.

جمع آوری داده های مورد نیاز در ماه تقریباً 12 رکورد بود. به نظر می رسد دستور select زمان زیادی را صرف کرده و تراکنش برای مدت طولانی اجرا نشده است.

DB

این اساسا جدولی است که هر روز حدود 400 ورودی افزایش می یابد. پایگاه داده قرار بود فقط برای ماه گذشته داده جمع آوری کند، بنابراین انتظار می رفت دقیقاً در برابر این حجم از داده ها مقاومت کند، اما متأسفانه عملیات چرخش گنجانده نشد.

این پایگاه داده توسط من ساخته نشده است. من آن را از یک توسعه دهنده دیگر تحویل گرفتم، بنابراین هنوز مانند بدهی فنی به نظر می رسید.

به نقطه ای رسید که حجم داده های درج روزانه زیاد شد و در نهایت به حد خود رسید. فرض بر این است که هنگام کار با چنین حجم زیادی از داده ها، جداسازی آنها ضروری است، اما متاسفانه این کار انجام نشد.

و بعد وارد عمل شدم.

تصحیح

کاهش اندازه خود پایگاه داده و کاهش زمان پردازش آن منطقی تر از تغییر خود منطق بود.

اگر 300 میلیون رکورد را پاک کنید، وضعیت باید به طور قابل توجهی تغییر کند، بنابراین تصمیم گرفتم این کار را انجام دهم ... اوه، فکر می کردم این قطعاً کار می کند.

اقدام 1

با تهیه یک نسخه پشتیبان قابل اعتماد، در نهایت شروع به ارسال درخواست کردم.

「ارسال درخواست」

DELETE FROM hoge_table WHERE create_time <= 'YYYY-MM-DD HH:MM:SS';

"..."

"..."

«هوم... جوابی نیست. شاید این پروسه خیلی طول بکشد؟» - فکر کردم، اما در هر صورت، به grafana نگاه کردم و دیدم که بار دیسک خیلی سریع در حال افزایش است.
دوباره فکر کردم "خطرناک است" و بلافاصله درخواست را متوقف کردم.

اقدام 2

پس از تجزیه و تحلیل همه چیز، متوجه شدم که حجم داده ها برای حذف همه چیز به یکباره بسیار زیاد است.

تصمیم گرفتم اسکریپتی بنویسم که بتواند حدود 1 رکورد را حذف کند و آن را راه اندازی کردم.

「من اسکریپت را پیاده می کنم」

فکر کردم: «اکنون این قطعاً کار خواهد کرد.

اقدام 3

روش دوم مؤثر بود، اما معلوم شد که بسیار کار بر است.
انجام همه کارها با دقت، بدون اعصاب غیر ضروری، حدود دو هفته طول می کشد. اما با این حال، این سناریو الزامات خدمات را برآورده نمی کرد، بنابراین مجبور شدیم از آن دور شویم.

بنابراین این چیزی است که من تصمیم گرفتم انجام دهم:

جدول را کپی کنید و نام آن را تغییر دهید

از مرحله قبل، متوجه شدم که حذف چنین حجم زیادی از داده ها، بار به همان اندازه بزرگ ایجاد می کند. بنابراین تصمیم گرفتم با استفاده از insert یک جدول جدید از ابتدا ایجاد کنم و داده هایی را که می خواستم حذف کنم به آن منتقل کنم.

| hoge_table     | 350'000'000|
| tmp_hoge_table |  50'000'000|

اگر جدول جدید را به اندازه بالا بسازید، سرعت پردازش داده نیز باید 1/7 سریعتر شود.

پس از ایجاد جدول و تغییر نام آن، شروع به استفاده از آن به عنوان جدول اصلی کردم. حالا اگر جدول 300 میلیون رکورد را رها کنم همه چیز خوب است.
متوجه شدم که بریدن یا دراپ سربار کمتری نسبت به حذف ایجاد می کند و تصمیم گرفتم از این روش استفاده کنم.

کارایی

「ارسال درخواست」

INSERT INTO tmp_hoge_table SELECT FROM hoge_table create_time > 'YYYY-MM-DD HH:MM:SS';

"..."
"..."
"ام...؟"

اقدام 4

فکر می کردم ایده قبلی جواب می دهد، اما پس از ارسال درخواست درج، چندین خطا ظاهر شد. MySQL بخشنده نیست.

من قبلاً آنقدر خسته بودم که شروع کردم به فکر کردن که دیگر نمی خواهم این کار را انجام دهم.

نشستم و فکر کردم و متوجه شدم که شاید برای یک بار درخواست های درج زیادی وجود داشته باشد ...
من سعی کردم یک درخواست درج برای مقدار داده ای که پایگاه داده باید در 1 روز پردازش کند ارسال کنم. اتفاق افتاد!

خوب، پس از آن ما به ارسال درخواست برای همان مقدار داده ادامه می دهیم. از آنجایی که باید داده های یک ماهه را حذف کنیم، این عمل را تقریباً 35 بار تکرار می کنیم.

تغییر نام جدول

در اینجا شانس با من بود: همه چیز به آرامی پیش رفت.

هشدار ناپدید شد

سرعت پردازش دسته ای افزایش یافته است.

قبلا این فرآیند حدود یک ساعت طول می کشید، اکنون حدود 2 دقیقه طول می کشد.

بعد از اینکه مطمئن شدم همه مشکلات حل شده، 300 میلیون رکورد را رها کردم. جدول را حذف کردم و احساس کردم دوباره متولد شده ام.

خلاصه

متوجه شدم که پردازش چرخشی در پردازش دسته ای وجود ندارد و این مشکل اصلی بود. این نوع خطای معماری منجر به اتلاف وقت می شود.

آیا هنگام حذف رکوردها از پایگاه داده به بارگیری در حین تکرار داده ها فکر می کنید؟ اجازه دهید MySQL را بیش از حد بارگذاری نکنیم.

کسانی که به دیتابیس مسلط هستند قطعا با چنین مشکلی مواجه نخواهند شد. برای بقیه شما، امیدوارم این مقاله مفید بوده باشد.

با تشکر برای خواندن!

بسیار خوشحال خواهیم شد اگر به ما بگویید که آیا این مقاله را دوست داشتید، آیا ترجمه واضح است، آیا برای شما مفید بوده است یا خیر؟

منبع: www.habr.com

اضافه کردن نظر