ORM یاد گرفتم، اما SQL بیشتر به دردم خورد
خلاصهٔ کاملتر
نویسنده این پست ۳۰ ماهه داره با Postgres و SQLite کار میکنه و در این مدت هم با SQLAlchemy (که ازش خوشش میاد) و هم با Hibernate (که ازش خوشش نمیاد) سروکار داشته. به گفتهٔ اون، بعد از این همه تجربه به این نتیجه رسیده که ORMها بیشتر ضرر دارن تا فایده و بهتره جای جایگزین کردن SQL، فقط کنارش استفاده بشن.
یکی از بزرگترین مشکلاتی که نویسنده باهاش روبرو شده «رشد بیرویهٔ ستونها»ست: جدولهایی که هی ستون جدید بهشون اضافه میشه تا دادههای متنوع مشتریها رو نگه دارن. وقتی یه کوئری مستقیم از روی خود اِنتیتی ساخته بشه، مثلاً:
query(Foo.class).add(Restriction.eq("x", value))این کار وقتی Foo پنج تا فیلد داره مشکلی نداره، ولی وقتی صد تا فیلد داشته باشه دقیقاً مثل SELECT * عمل میکنه و دادههای اضافی رو منتقل میکنه. نویسنده میگه با اضافه کردن پروجکشن درست، یه کوئری از چند دقیقه به چند ثانیه رسونده.
مشکل بعدی، کلیدهای خارجی مدیریتنشدهست: تو یکی از پروژههاش یه جدول با بیش از ۶۰۰ فیلد و ۱۴ تا جوین برای گرفتن فقط یه آبجکت داشته. نتیجهای که نویسنده میگیره اینه که برای استفادهٔ درست از ORM بازم باید SQL بلد باشی، پس چرا مستقیم خود SQL رو یاد نگیری؟
تو بخش دیتا ریتریوال هم میگه هر چی مدل داده پیچیدهتر باشه، بیشتر باید با ORM کلنجار بری تا کوئری بهینه تولید بشه؛ چیزهایی مثل window functions تقریباً نوشتنشون با ORM شکنجهست. راهحلی که خودش پیدا کرده، نوشتن کوئری با یه سیستم templating و توصیف جدولها با ORMه؛ هم راحتیِ توصیف اپلیکیشنمحور رو داره، هم مستقیم از SQL استفاده میکنه.
مشکل «دو-اسکیمایی» هم یکی دیگه از دغدغههای نویسندهست: تعریف داده هم تو دیتابیس هست هم تو اپلیکیشن، و مهاجرت مدل تو اپلیکیشن راحته ولی تو دیتابیس دردسرِ واقعیه. نویسنده ترجیح میده تعریف داده رو تو دیتابیس نگه داره و فقط نتیجهٔ کوئریها رو به عنوان API دیتابیس در نظر بگیره، نه خود جدولها رو.
دربارهٔ شناسهها هم میگه تو اپلیکیشن معمولاً شناسه یعنی آدرس حافظه، ولی تو دیتابیس شناسه یعنی وضعیت خودِ رکورد؛ این دوتا خوب باهم جور نمیشن و باعث میشه مجبور بشی دستی کش رو flush کنی یا partial commit بزنی تا شناسهٔ واقعی دیتابیس رو بگیری. تراکنشها هم به گفتهٔ نویسنده بهخاطر scope دینامیکیشون، با کدنویسی معمولی و lexical scoping جور درنمیان و باعث میشن مجبور بشی session رو همهجا پاس بدی.
نویسنده در پایان میگه داره به سمت استفاده از stored procedureها فکر میکنه و دیتابیس رو مثل یه data type بزرگ با یه سری کوئری بهعنوان API نگاه میکنه، نه جایی برای ذخیرهٔ آبجکتهای برنامه. جمعبندیش اینه: ORM راهیه قابل قبول برای توصیف داده، ولی راه بدی برای نوشتن کوئری و ذخیرهٔ وضعیت آبجکته - اگه داری از یه دیتابیس رابطهای استفاده میکنی، دلتو بزن به دریا و SQL رو یاد بگیر.
نکات کلیدی:
- ORMها مشکلاتی مثل رشد بیرویهٔ ستونها، جوینهای زیاد روی کلیدهای خارجی، و کوئریهای ناکارآمد رو مخفی نمیکنن
- برای استفادهٔ مؤثر از ORM هم بازم باید SQL بلد باشی
- تناقض بین شناسهٔ اپلیکیشن و دیتابیس و مدیریت تراکنشها از دردسرهای اصلی ORMه
- نویسنده بهجای ORM سنتی به templating SQL و حتی stored procedureها گرایش پیدا کرده




