نکته مهم در export کردن، تغییرات و import کردن دیتا (ETL)

سلام دوستان. میخوام چند نکته مهم در مورد دیتابیس بگم که حتما به کارتون میاد. داستان از جایی شروع شد که من روی یک پروژه قدیمی کار می‌کردم که استارتش از زمانی خورده بود که تازه برنامه نویسی یاد گرفته بودم. در نتیجه کد ها به شدت بد بودن، ساختار پایگاه داده افتضاح بود و برنامه دیگه قابلیت به روزرسانی نداشت. پس تصمیم گرفتم یه آپدیت کلی بکنم و همه چیز رو از اول بنویسم و بسازم.مهمترین قسمت آپدیت این برنامه تغییر توی پایگاه داده بود. همونطور که گفتم ساختار پایگاه داده افتضاح بود و حتی name convention ها رو هم رعایت نکرده بودم یک جا به صورت camelCase بود و جای دیگه snake_case بود. در نتیجه باید کل ساختار دیتا بیس رو تغییر می‌دادم. یک سری از جدول ها با هم ادغام می‌شدند و یک سری دیگه باید جدا می‌شدند. خوب توی این روند یه سری موارد رو فهمیدم که در ادامه باهاتون به اشتراک میگذارم.برای جدول ها ID بگذاریدچند روز پیش برام سوال شده بود که آیا برای جدول ها باید حتما ID بگذاریم یا نه؟ چون بعضی از جدول ها واقعا نیاز به ID ندارن مثلا جدول هایی که رابط دو جدول دیگه هستند. ولی توی این روند فهمیدم که حتما باید برای جداول ID بگذاریم که در ادامه توضیح میدم چرا.مشکل بزرگخوب بزرگترین مشکلی که من داشتم این بود که بعضی از جدول ها بیش از 10 ها ملیون رکورد داشت و خوب وقتی جدولی به این بزرگیه نمیشه با یک دستور insert into اون رو تغییر داد و ریخت توی یک جدول دیگه. باید اینجا از صف ها کمک بگیریم که خوب من چون از لاراول استفاده میکردم به کمک کوئری بویلدر و صفها در لاراول این کار رو انجام دادم. (اینجا منظورم از کوئری بویلدر ORM نیست). ولی یک مشکل بزرگ دیگه هنوز هست. و اون گرفتن هر بخش توی هر بار پردازش هست.گرفتن بخش های مختلف یک جدولخوب شاید اولین چیزی که به ذهن شما برسه مثل من استفاده از LIMIT و OFFSET باشه پس من هم همین کار رو کردم و برای مثلا LIMIT رو گذاشتم روی 1000 و OFFSET رو هم توی هر مرحله 1000 تا بیشتر می‌کردم. و جدولی که 12 ملیون رکورد داشت حدود 12 ساعت طول کشید تا انتقال پیدا کرد به جدول جدید. و حس کردم این غیر طبیعیه ولی چون تجربه نداشتم گفتم حتما طبیعیه.اما بعد از این یک اشتباه کوچیک در دستورات artisan لاراول باعث شد تمام رکورد های جدول جدید دوباره پاک بشه و اینجا بود که دوباره از اول فرایند انتقال رو انجام دادم. در این بین داشتم نگاه میکردم دیدم هرچی میگذره عملیات کند تر میشه، یعنی 1000 مرحله اوله توی کمتر از چند دقیقه انجام میشد ولی بعدش زمانش بیشتر و بیشتر میشد به صورت تساعدی. اولش فکر کردم شاید چون جدول جدید رکورد هاش بیشتر میشه عملیات INSERT کند میشه ولی بعد گفتم نکنه عملیات SELECT کند تر میشه با زیاد شدن OFFSET.بنابرین چنتا کوئری زدم و دیدم بله عملیات SELECT از جدول قدیمی با بیشتر شدن OFFSET بیشتر میشه. چنتا سرچ کردم و دیدم دقیقا رابطه مستقیم داره و وقتی OFFSET بیشتر میشه درواقع دیتابیس میاد و رکوردهای اولیه رو هم میگیره، برای همین هرچی پیش میرفت به صورت تساعدی کند می‌شد.راه حل چیه؟راه حل اینه که به جای اینکه از OFFSET و LIMIT بیایم و از ID استفاده کنیم. یعنی رکورد ها رو بر اساس ID باید ORDER کنید و بعد مثلا هر بار 1000 تا ID جدید رو بگیرید. وقتی این کار رو کردم اون عملیانی که 12 ساعت طول کشید در کمتر از یک ساعت تموم شد.نکته خیلی مهم در مورد gap بین ID هاخوب ممکنه به دلایل مختلف بین ID های شما فاصله زیادی باشه. بهترین راه برای اینکه هم زمان کمتری ازتون گرفته بشه و هم دوباره بین ID های جدید فاصله کمتر ایجاد بشه اینه که بیاین قبل از شروع هر صف این فاصله ها را حساب کنید مثلا یک سری کوئری بزنید که هر هزارتا ID رو بگیره و مقدار آخرش رو ذخیره کنه برای شروع بعدی. مثلا در نهایت همچنین آرایه‌ای داشته باشید. و توی SELECT لحاظش کنید.[ [&quotstart&quot=>0,&quotend&quot=>12236] [&quotstart&quot=>12236,&quotend&quot=>25635] [&quotstart&quot=>25635,&quotend&quot=>35698] . . . ]سخن آخرپس حتما برای جدول ها ID قرار بدید تا در این مواقع بتونید استفاده کنید. امیدوارم به دردتون بخوره و وقتتون مثل من از بین نره.