مهندسی داده
792 subscribers
112 photos
7 videos
24 files
314 links
BigData.ir کانال رسمی وب سایت
مطالبی راجع به مهندسی داده و طراحی زیرساخت‌های پردازش دیتا و ابزارهای مدرن دیتا
ارتباط با ادمین: @smbanaei
گروه تخصصی مهندسی داده 👇
https://t.iss.one/bigdata_ir_discussions2
کانال یوتیوب 👇
https://www.youtube.com/@irbigdata
Download Telegram
چرا دریافت نتایج کوئری گاهی اینقدر طول می‌کشد؟

با پیشرفت روزافزون فناوری دیتابیس‌ها، ضروری است که روش‌ها و پروتکل‌های انتقال داده نیز به‌روزرسانی شوند تا بتوان از تمامی ظرفیت و توان پردازشی این سیستم‌ها به‌طور مؤثر بهره‌برداری کرد.

فرض کنید به عنوان یک تحلیلگر داده، با استفاده از درایور ODBC به ClickHouse متصل شده‌اید و دستوری برای بازیابی ۱۰ هزار رکورد خاص اجرا کرده‌اید. دستور را ارسال می‌کنید و منتظر نتایج می‌مانید، اما متوجه می‌شوید که زمان دریافت نتایج به طرز معناداری بیشتر از زمانی است که همان دستور را مستقیماً در خط فرمان ClickHouse اجرا کرده‌اید. 😕 این تفاوت زمانی از کجا می‌آید و چرا برای کاربرانی مثل شما که با داده‌های بزرگ کار می‌کنید، مهم است؟

دلیل اصلی این کندی، به نحوه عملکرد درایورهای سنتی مانند ODBC برمی‌گردد. ClickHouse یک دیتابیس تحلیلی است که از ذخیره‌سازی ستونی استفاده می‌کند—ساختاری که برای پردازش سریع داده‌های حجیم بهینه شده است. اما درایورهای ODBC برای دیتابیس‌های ردیفی طراحی شده‌اند و مجبورند داده‌های ستونی را به فرمت ردیفی تبدیل کنند. این تبدیل، هم زمان‌بر است و هم منابع زیادی مصرف می‌کند، که نتیجه‌اش کاهش عملکرد و تأخیر در دریافت داده‌هاست. برای تحلیلگران داده، مهندسین داده و دانشمندان داده که به سرعت و کارایی وابسته هستند، این یک چالش جدی است.

🚀 فرمت Arrow: استانداردی برای پردازش سریع داده‌های تحلیلی
سال‌هاست که Apache Arrow به عنوان یک فرمت درون حافظه برای کار با داده‌های ستونی، به یک استاندارد رایج برای پردازش سریع و بهینه داده‌های تحلیلی تبدیل شده است. Arrow با طراحی خاص خود، سربار ناشی از تبدیل داده‌ها بین فرمت‌های مختلف را حذف می‌کند و امکان پردازش موازی را فراهم می‌آورد. این یعنی شما می‌توانید داده‌های بزرگ را با سرعت بیشتری تحلیل کنید. 📊 این فرمت با ابزارهای محبوبی مثل Pandas، Apache Spark و Dask سازگار است و به همین دلیل، برای جامعه داده به یک انتخاب ایده‌آل تبدیل شده است.

حالا تصور کنید اگر بتوانید همین سرعت و کارایی را مستقیماً در ارتباط با دیتابیس‌ داشته باشید. ADBC دقیقا با همین هدف و توسط پروژه محبوب Arrow توسعه داده شد.

🌟 کتابخانه ADBC: راهکاری مدرن برای ارتباط سریع با دیتابیس‌ها
اینجاست که ADBC (Arrow Database Connectivity) وارد می‌شود! ADBC یک رابط برنامه‌نویسی کاربردی (API) مدرن است که به شما اجازه می‌دهد داده‌ها را به صورت مستقیم و در فرمت ستونی از دیتابیس‌هایی مثل ClickHouse یا حتی پستگرس دریافت کنید. با ADBC، دیگر نیازی به تبدیل‌های وقت‌گیر به فرمت ردیفی نیست—داده‌ها با همان ساختار ستونی که برای تحلیل بهینه است، به اپلیکیشن شما منتقل می‌شوند. 🚄

🎯 مزایای ADBC برای تحلیلگران و مهندسین داده
- سرعت بیشتر: حذف تبدیل‌های ردیفی، زمان دریافت داده‌ها را به شدت کاهش می‌دهد.
- پشتیبانی از استریمینگ: داده‌ها به صورت پیوسته و بدون وقفه منتقل می‌شوند.
- انعطاف‌پذیری: با دیتابیس‌های مختلف، از ClickHouse تا PostgreSQL، کار می‌کند.
- اکوسیستم کامل: یک API یکپارچه با ابزارهایی مثل Flight SQL که کار توسعه و کاربرد آنرا ساده‌تر می‌کنند.

برای پروژه‌های تحلیلی که زمان و دقت در آن‌ها حرف اول را می‌زند، تفاوت سرعت ناشی از به کار گیری ADBC برای اتصال به دیتابیس‌ها می‌تواند بهره‌وری شما را متحول کند. 📈
نکته مهم دیگری که باید اشاره شود این است که حتی برای دیتابیس‌های کلاسیک، اگر قصد دریافت حجم زیاد دیتا برای پردازش با ابزارهایی مانند پانداز یا polars را دارید، باز هم ADBC بهینه‌تر است. مثال موجود در شکل این پست هم در همین راستاست.

#DataEngineering #Database #ADBC #ApacheArrow #BigData #PerformanceOptimization #DuckDB #PostgreSQL


منبع : https://arrow.apache.org/blog/2025/02/28/data-wants-to-be-free/
👍61
چرا UUID7 و ULID گزینه‌های بهتری برای کلیدهای اصلی در پایگاه داده هستند؟
در طراحی پایگاه‌های داده، انتخاب نوع شناسه (ID) یکی از تصمیم‌های کلیدی است که می‌تواند تأثیر زیادی بر عملکرد، مقیاس‌پذیری و امنیت سیستم داشته باشد.
در سناریوهایی مثل سیستم‌های توزیع‌شده، APIهای پرترافیک یا صفحات محصول در وب‌سایت‌ها که نیاز به درج سریع داده و جلوگیری از افشای الگوی رکوردها وجود دارد، استفاده از کلیدهای auto-increment معمولاً گزینه مناسبی نیست. چون:
⛔️باعث قفل شدن جدول در شرایط همزمانی بالا می‌شود،
⛔️امکان حدس زدن تعداد یا ترتیب رکوردها را فراهم می‌کند.

💡 راه‌حل سنتی چیست؟
استفاده از UUID (نسخه ۴) به‌عنوان کلید اصلی مزایای خوبی دارد: یکتایی جهانی بدون نیاز به هماهنگی بین سرورها، مناسب برای محیط‌های توزیع‌شده، و جلوگیری از افشای الگوهای داده. اما یک مشکل جدی دارد.
🔍 چرا UUID تصادفی (مثلاً UUIDv4) در دیتابیس‌ها عملکرد خوبی ندارد؟
اکثر پایگاه‌های داده رابطه‌ای مانند PostgreSQL، MySQL و SQL Server برای ایندکس‌گذاری — مخصوصاً روی کلید اصلی — از ساختاری به‌نام B-Tree (Balanced Tree) استفاده می‌کنند.
این ساختار کمک می‌کند:
✳️جستجوی کلیدها با پیچیدگی O(log n) انجام شود (سریع و مقیاس‌پذیر)،
✳️داده‌ها به‌صورت مرتب نگه داشته شوند،
✳️ و درج، حذف یا به‌روزرسانی به‌شکل کارآمد مدیریت شود.
اما مشکل از جایی شروع می‌شود که کلیدهایی با ترتیب تصادفی (مثل UUIDv4) در جدول وارد می‌شوند.

📉 چه اتفاقی می‌افتد؟
وقتی داده‌های زیادی با کلید تصادفی وارد جدول می‌شوند:
⛔️ دیتابیس نمی‌تواند آن‌ها را در انتهای ساختار درختی اضافه کند (مثل auto-increment IDs)،
⛔️ باید آن‌ها را بین صفحات مختلف B-Tree پراکنده کند،
⛔️ این پراکندگی باعث عملیات مکرر Page Split (شکستن صفحات)، جابه‌جایی نودها و بازچینش ساختار درختی می‌شود.


🧨 نتیجه؟
🧱کند شدن محسوس عملیات درج (INSERT)،
🧱 مصرف بالای I/O و حافظه،
🧱 کاهش عملکرد کلی سیستم در سناریوهای پرترافیک.

راه‌حل‌های مدرن: UUID7 و ULID
برای رفع این مشکلات، دو استاندارد جدید معرفی شده‌اند:
🔹 استاندارد ULID (Lexicographically sortable): ترکیبی از timestamp و داده تصادفی
🔹 استاندارد UUIDv7: نسخه‌ای از UUID با ترتیب زمانی، سازگار با استاندارد UUID

مزیت اصلی این دو چیست؟

🔸 با حفظ یکتایی و امنیت، کلیدها به‌صورت ترتیبی در ایندکس درج می‌شوند.
🔸 این یعنی:
کاهش شدید Page Split و پراکندگی
بهبود درج‌های پرترافیک
جست‌وجوی سریع‌تر بر اساس بازه‌های زمانی

📊 چه زمانی از هرکدام استفاده کنیم؟
اگر خوانایی و طول کوتاه‌تر مهم است → ULID
اگر سازگاری با UUID استاندارد اهمیت دارد → UUIDv7

📐 قالب ULID
قالب ULID یک رشته ۲۶ نویسه‌ای است که با Crockford’s Base32 کدگذاری می‌شود (حروف I, L, O, U حذف شده‌اند تا اشتباه نشوند).
→ طول: ۲۶ نویسه - کاراکترهای ابتدایی مهرزمان هستند.
→ مثال: 01AN4Z07BY79KA1307SR9X4MV3

📐 قالب UUIDv7
→ نمایش به‌صورت استاندارد UUID در مبنای ۱۶ (hex) با خط تیره
→ طول شامل خط تیره: ۳۶ نویسه - کاراکترهای ابتدایی مهرزمان هستند.
→ قالب: 8-4-4-4-12
→ مثال: 017f45e0-7e1a-7a3f-8bbc-4dbf7e6d9c3a
→ طول بدون خط تیره: ۳۲ نویسه hex

بنابراین UUID7 طول بیشتری نسبت به ULID دارد اما چون با استاندارد UUID سازگاراست، برای سیستم‌های موجود گزینه بهتری است.

#Database #Backend #DistributedSystems #UUID #ULID #PostgreSQL #SystemDesign #Performance #مهندسی_داده
👍81
الگوی Outbox و داستان یک راهکار هوشمندانه در پستگرس

اخیراً مقاله‌ای از صادق دوستی در Dev.to خواندم که نشان داد با تجربه و تسلط، می‌توان برای چالش‌های بزرگ، راه‌حل‌هایی هوشمندانه و ساده پیدا کرد. یعنی در دنیای فنی، گاهی غرق پیچیدگی‌ها می‌شویم و راه‌حل‌های ساده اما عمیق را نادیده می‌گیریم. این پست ادای دینی است به صادق عزیز Sadeq Dousti و مقالات ارزشمندش، و مروری بر مشکل پیاده‌سازی الگوی Outbox با PostgreSQL در حجم بالای داده و راه‌حلی خلاقانه برای آن.


https://dev.to/msdousti/postgresql-outbox-pattern-revamped-part-1-3lai/



🎯 الگوی Outbox چیست؟

در یک فروشگاه آنلاین، ثبت سفارش باید چند کار را انجام دهد:

ذخیره در پایگاه داده

ارسال ایمیل تأیید

به‌روزرسانی موجودی

اطلاع به واحد ارسال

این اکشن‌ها به بروکرهایی مثل Kafka ارسال می‌شوند تا هر واحد کار خود را انجام دهد.

اگر ارسال پیام به بروکر با خطا مواجه شود؟

Outbox وارد می‌شود! سفارش در پایگاه داده ذخیره شده و یک پیام در جدول Outbox ثبت می‌شود. یک سرویس جداگانه پیام‌ها را خوانده و به بروکر می‌فرستد. در صورت خطا، پیام در جدول باقی می‌ماند تا دوباره برای پردازش ارسال شود اما ...



🔍 چالش: حجم بالای داده‌ها

با افزایش پیام‌ها در Outbox:

⚠️کوئری‌های خواندن پیام‌های منتشرنشده کند می‌شوند.

⚠️ایندکس‌ها به دلیل آپدیت‌های مکرر غیربهینه می‌شوند.

⚠️مصرف منابع سیستم افزایش می‌یابد.



💡 راه‌حل: پارتیشن‌بندی هوشمند

صادق دوستی پیشنهاد می‌کند جدول Outbox را به دو پارتیشن تقسیم کنیم:

outbox_unpublished: پیام‌های منتشرنشده (published_at IS NULL)

outbox_published: پیام‌های منتشرشده (published_at NOT NULL)

با این کار، پیام‌های جدید به outbox_unpublished می‌روند و پس از انتشار، به‌صورت خودکار به outbox_published منتقل می‌شوند. بنابراین کوئری‌ها فقط روی پارتیشن سبک‌تر اجرا می‌شوند.



🎉 مزایا:


سرعت بالا: کوئری‌ها روی پارتیشن کوچک‌تر اجرا می‌شوند.

مدیریت آسان: حذف پیام‌های قدیمی با TRUNCATE سریع است.

بهینه‌سازی منابع: ایندکس‌ها کوچک و کارآمد می‌مانند.



🏁 جمع‌بندی


الگوی Outbox برای هماهنگی سیستم‌های توزیع‌شده عالی است، اما پیاده‌سازی نادرست آن مشکل‌ساز می‌شود. پارتیشن‌بندی هوشمند صادق دوستی این الگو را بهینه‌تر و سریع‌تر می‌کند.

🔗 برای جزئیات بیشتر، حتا مقاله صادق در Dev.to را بخوانید!

#outbox #postgres #performance #database #dataengineering

#مهندسی_داده
👍1
بررسی تغییرات پایگاه‌های داده در نظرسنجی Stack Overflow 2025📊

نظرسنجی سالانه Stack Overflow برای سال 2025 منتشر شده و یافته‌های قابل‌توجهی را در خصوص روند استفاده از پایگاه‌های داده در میان توسعه‌دهندگان حرفه‌ای ارائه می‌دهد.

آدرس نظر سنجی :

Technology | 2025 Stack Overflow Developer Survey

در این پست نگاهی خواهیم داشت به وضعیت پستگرس‌کیوال (PostgreSQL)، رشدهای چشمگیر و همچنین کاهش‌ها و غیبت‌های معنادار. 🚀

🏆 پستگرس PostgreSQL: ادامه‌ سلطه با رشد پایدار

پستگرس با ثبت رشد ۱۰٪ نسبت به سال گذشته و رسیدن به نرخ استفاده ۵۵.۶٪، جایگاه نخست خود را در میان پایگاه‌های داده محبوب حفظ کرده است. از سال ۲۰۲۳، این پایگاه داده به‌عنوان "مطلوب‌ترین" (۴۶.۵٪) و "تحسین‌شده‌ترین" (۶۵.۵٪) گزینه نزد توسعه‌دهندگان شناخته می‌شود. 😍


🔍 دلایل اصلی محبوبیت PostgreSQL:

انعطاف‌پذیری بالا: پشتیبانی از داده‌های رابطه‌ای و غیررابطه‌ای مانند JSON.

جامعه متن‌باز قدرتمند: توسعه مداوم و اسناد جامع.

عملکرد مناسب برای سناریوهای پیچیده: پاسخ‌گویی به بارهای کاری سنگین و ساختارهای داده پیشرفته.

📈 پایگاه‌های داده با رشد چشمگیر

🎯 ردیس: با رشد ۱۰٪ به ۲۸٪ رسید و با عبور از MongoDB به رتبه پنجم صعود کرد. ⚡️ همچنین Valkey نیز با ۲.۵٪ ورود قابل‌توجهی به صحنه داشت.

🎯 الستیک سرچ: با افزایش ۵٪، به نرخ استفاده ۱۶.۷٪ رسید؛ رشدی معنادار برای این موتور جستجوی داده.

🎯 دیتابیس DuckDB: با دو برابر شدن سهم خود به ۳.۲٪، توجه‌ها را به سمت خود جلب کرده است.

🎯 خدمات ابری Supabase: از ۴.۱٪ به ۶٪ رسید و برای نخستین‌بار وارد جمع ۱۲ پایگاه داده برتر شد. 🎉

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


📉 پایگاه‌های داده با کاهش استفاده


⚠️ مای اسکیوال MySQL: با کاهش جزئی به ۴۰.۵٪، روندی آهسته اما قابل مشاهده را تجربه کرده است.

⚠️مانگودی بی MongoDB: با رسیدن به ۲۴٪، افتی کمتر از پیش‌بینی‌ها داشته، اما جایگاه خود را در رقابت از دست داده است.


غایب بزرگ

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


🌟 تمایل توسعه‌دهندگان به یادگیری PostgreSQL

یکی از نکات جالب این گزارش، تمایل بالای کاربران Redis و MongoDB به یادگیری PostgreSQL است. این روند نشان می‌دهد مهارت در پایگاه‌های داده رابطه‌ای همچنان یکی از مزیت‌های کلیدی در مسیر حرفه‌ای توسعه‌دهندگان است. 📈


💡 چرا این موضوع تمایل به استفاده از پستگرس اهمیت دارد؟

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




#StackOverflow2025 #PostgreSQL #Database #توسعه_نرم‌افزار #فناوری #دیتابیس #تحلیل_داده
👍2
وقتی SQL هم حلقه For دارد! نگاهی به Lateral Join در PostgreSQL

اگر در حوزه نرم‌افزار، تحلیل داده یا دیتابیس کار می‌کنید، احتمالاً با انواع JOIN‌های معمول در SQL مثل INNER JOIN و LEFT JOIN آشنا هستید.

اما یکی از جوین‌هایی که کمتر درباره‌اش صحبت می‌شود و در عین حال بسیار مفید و کاربردی محسوب می‌شود، LATERAL JOIN است.

بیایید با یک مثال شروع کنیم 👇

فرض کنید یک جدول از محصولات دارید و می‌خواهید برای هر محصول، آمارهایی مثل:

🔰 مجموع کل فروش،

🔰حجم فروش،

🔰تعداد مشتریان منحصربه‌فرد،

🔰و میانگین فروش

در سه ماه گذشته را به‌دست آورید (به تفکیک ماه).

اگر بخواهید این کار را با زبان‌هایی مثل Python یا JavaScript انجام دهید، معمولاً یک حلقه (for) روی تمام محصولات اجرا می‌کنید و درون آن، برای هر محصول، محاسبات آماری مربوط به فروش را انجام می‌دهید.

در واقع، یک حلقه بیرونی برای محصولات و یک حلقه داخلی برای فروش‌های هر محصول دارید. در SQL هم می‌توان دقیقاً همین رفتار را شبیه‌سازی کرد: با استفاده از LATERAL JOIN.

اینجاست که Lateral مثل یک پل ارتباطی عمل می‌کند:

⚡️ به زیرکوئری اجازه می‌دهد به داده‌های هر ردیف از جدول اصلی دسترسی داشته باشد. یعنی در زیرکوئری، رکوردها ابتدا بر اساس رابطه آنها با جدول اصلی فیلتر می‌شوند و سپس محاسبات آماری روی آنها انجام میشود و نهایتا هم در کنار رکوردهای جدول اصلی قرار می‌گیرند.


به همین دلیل معمولاً از CROSS JOIN LATERAL استفاده می‌کنیم، چون شرط اتصال درون زیرکوئری و با WHERE تعریف می‌شود و در اینجا Inner Join معنا نخواهد داشت.

💫 نتیجه این رهیافت

می‌توانید به‌سادگی کوئری‌هایی بنویسید که مثلاً:

🌟 «ده محصول پرفروش هر کتگوری» را پیدا کند،

🌟یا برای هر مشتری، آخرین تراکنش ثبت‌شده‌اش را نمایش دهد،

🌟یا حتی تحلیل‌های زمانی و Top-N را مستقیماً داخل SQL انجام دهد: بدون نیاز به کدهای پیچیده و توابع پنجره‌ای


🎥 برای آشنایی دقیق‌تر با این مفهوم، یک ویدئوی آموزشی حدود ۴۰ دقیقه‌ای آماده کرده‌ام که در آن، با مثال‌های واقعی و کاربردی نحوه‌ی استفاده از LATERAL JOIN را گام‌به‌گام توضیح داده‌ام.

🔗 لینک مشاهده ویدئو در یوتیوب:

👉 https://youtu.be/vVc2EewTSQU


💡 در این ویدئو یاد موارد زیر را به صورت عملی مرور می‌کنیم:

ایده‌ی اصلی و کاربرد LATERAL JOIN

تفاوت آن با جوین‌های معمول

نوشتن کوئری‌های Top-N per Group

تحلیل داده‌های واقعی (مشتریان، فروش، زمان)

و نکات مهم برای بهینه‌سازی عملکرد کوئری


📚 این ویدئو بخشی از دوره‌ی PostgreSQL Practical Course در مدرسه مهندسی داده سپهرام است.

👉 https://sepahram.ir/courses


#PostgreSQL #SQL #DataEngineering #Database #LateralJoin #Sepahram #BigData #PostgresTutorial #Analytics
8👍2