چرا DuckDB 2.0 سریعتر است
آدرس مقاله: https://motherduck.com/blog/why-duckdb-20-is-faster/ آدرس نظرات: https://news.ycombinator.com/item?id=50035530 امتیاز: 200 # نظر: 62
DuckDB 2.0 پاییز امسال منتشر می شود و آلفا منتشر می شود! من ویژگیهای جالب را روی لپتاپ خودم و در مقابل S3 اجرا کردم تا ببینم واقعا چه چیزی برای افرادی که جداول و خطوط لوله میسازند به جای موتورهای پایگاه داده تغییر میکند.
زیرا بله، DuckDB 2.0 سریعتر است. اما برای دستیابی به سرعت بالا باید بدانید که چگونه داده های شما شکل می گیرند و گاهی اوقات چگونه آن را مدل کنید.
این پست سه ویژگی را پوشش میدهد که فکر میکنم بیشترین اهمیت را دارند، با اعدادی که به دست آوردم، بهعلاوه چند گوهر پنهان که در گزارشهای commit پیدا کردم.
هر عدد زیر مربوط به یک دستگاه (یک لپ تاپ M5) و اینترنت خانگی من است که هر دو نسخه را تقریبا به یک اندازه کند می کند. قبل از نقل قول خود را اجرا کنید ;)
بیایید با سادهترین و هیجانانگیزترین مورد شروع کنیم: ورودی/خروجی async.
این موردی است که من بیشتر دوست دارم، زیرا هیچ چیز در درخواست شما تغییر نمی کند. در اینجا یک پرس و جو وجود دارد که یک فایل پارکت 2.2 گیگابایتی را در S3 می خواند (رای پشته سرریز، 228 میلیون ردیف، 2268 گروه ردیف) و تعداد آرا در هر نوع. این یک ستون از چهار، حدود 230 مگابایت را می خواند.
هشدار سریع: همانطور که در مقدمه گفتم، این اینترنت خانگی من به us-east-1 است، بنابراین هر دو عدد کند هستند. اگر این را از محاسبات ابری اجرا کنید، انتظار داشته باشید که همه چیز سریعتر پیش برود.
پس جادوی سیاه اینجا چیست؟ فایل به 2268 گروه ردیفی حدود 122000 ردیف بریده شده است. برای هر گروه ردیف، DuckDB بایت ها را دانلود می کند، پارکت را رمزگشایی می کند، آرا را در هر نوع می شمارد، و شمارش جزئی را در پایان ادغام می کند. دو نوع کار: انتظار در شبکه و سخت کردن CPU.
در 1.5.5 هر یک از 18 کارگر هر دو کار را به نوبه خود انجام می دهند: دانلود، صبر کنید، رمزگشایی، دانلود، صبر کنید. در حالی که یک کارگر منتظر است CPU آن بیکار است، در حالی که رمزگشایی می کند، هیچ بارگیری در حال پرواز ندارد و شما هرگز بیش از 18 بار دانلود نمی کنید.
در نسخه 2.0 یک مجموعه جداگانه از رشته ها فقط دانلود می شود، ده ها گروه ردیف را در حال پرواز نگه می دارد و بایت ها را در یک بافر پارک می کند. کارگران فقط رمزگشایی می کنند و همیشه یک گروه ردیف برای آنها آماده است. شبکه و CPU همزمان مشغول هستند.
یک تنظیم این را هدایت میکند: read_ahead_depth، چند گروه ردیفی که مجموعه دانلود ممکن است جلوتر از کارگران بگیرد. پیشفرض آن -1 است (خودکار، اندازه آن از تعداد رشتههای شما)، بنابراین ورودی/خروجی غیرهمگام در خارج از جعبه روشن است. آن را روی 0 تنظیم کنید و رفتار 1.5 را برمی گردانید.
یک نظر در مورد فایلهای کوچک: هیچ تغییر معنیداری وجود ندارد، زیرا زمان رفت و برگشت هر فایل (پانویس، سپس داده) وجود دارد که خواندن پیشرو نمیتواند حذف شود. ذخیره یک دریاچه به عنوان هزاران فایل پارکت 1 مگابایتی به هر حال عمل بدی است و 2.0 آن را نجات نمی دهد. اصول هنوز مهم است!
TL;DR: خواندن دادهها از طریق S3 2 برابر تا 3 برابر سریعتر در نسخه 2.0 با تغییرات پرس و جو صفر است، زیرا یک استخر مجزا جلوتر از کارگران دانلود میشود. به طور پیش فرض روشن است ( read_ahead_depth = -1 ); 0 به شما رفتار قدیمی را می دهد.
تیم DuckDB موتور بازگشتی CTE را بازنویسی کرد و ادعا می کند 40 برابر در دسترس بودن نمودار. نگران نباشید، من در جدولی که قبلا میدانید، توضیح میدهم که این به چه معناست.
یک CTE بازگشتی یک حلقه روی یک جدول است. یک جدول کارمندان با دو ستون، مدیر و کارمند را در نظر بگیرید. شما می خواهید به یک سوال ساده پاسخ دهید: چه کسی به چه کسی گزارش می دهد.
برای انجام این کار، شما با یک ردیف شروع می کنید: آنا، مدیرعامل. دور اول، همه را پیدا کنید که مدیر آنها آنا (بن، کلیا) است. دور دوم، هرکسی را پیدا کنید که مدیرش یکی از آن افراد باشد (دیو، الی، فی). ادامه دهید تا زمانی که یک دور هیچ کس جدیدی را پیدا نکند. هر سطح از نمودار سازمانی یک دور است.
نمودار سازمانی، درخت پوشه، صورتحساب مواد، رشته پاسخ، اصل و نسب داده، تاریخچه git: اینها همه انواع داده هایی هستند که در آن جدول اغلب دو ستون یکسان است، والد و فرزند. تنها چیزی که تفاوت دارد این است که عمق آن چقدر است و عمق تعداد دورهای پرس و جو است. یک نمودار سازمانی شاید هشت سطح باشد. تاریخچه git ده ها هزار است.
مشکل 1.5 اینجاست. هر دور، به عقب می رفت و کل جدول را دوباره می خواند تا سطح بعدی را پیدا کند. هشت سطح به معنای هشت خواندن کامل است. هزاران سطح، هزاران بار خوانده شده کامل از یک جدول. در 2.0 جدول یک بار خوانده می شود، جستجو در ستون والد یک بار ساخته می شود و هر دور فقط چند ردیفی را که تازه پیدا کرده است جستجو می کند. اکنون هزینه مربوط به ردیف هایی است که شما واقعا لمس می کنید، نه دور بر اندازه جدول.
با بازگشت به تاریخچه git، معمولا در آنجا شاهد افزایش خواهید بود. هر commit به والد خود اشاره می کند، بنابراین جدول فقط commit_id، parent_id است و قدم زدن در اصل و نسب HEAD یک دور در هر commit است. من یک مخزن 20000 commit با چند ادغام ایجاد کردم و آن را با یک CTE بازگشتی مانند این به ریشه بازگشتم:
TL;DR: اگر زنجیرههای عمیق والدین/فرزند (تاریخچه git، اصل و نسب، رشتههای پاسخ، صورتحساب کامل مطالب) را طی کنید، 2.0 کاری را که برای فشار دادن به پایگاه داده گراف استفاده میکردید به یک جستجوی معمولی تبدیل میکند. اگر سلسله مراتب شما کم عمق باشد، مانند نمودار سازمانی، چیز زیادی نخواهید دید. در هر صورت، سلسله مراتب را بهعنوان یک جدول والد/فرزند با شناسههای اعداد صحیح حفظ کنید و زمانی که بازگشت مقداری مانند عمق یا هزینه دارد، به استفاده از کلید برسید.
همه JSON را دوست دارند. VARIANT اکنون یک نوع داده درجه یک در DuckDB است و کلمه ای که باید به خاطر بسپارید خرد کردن است.
نه از نوع گیتار. خرد کردن در زمینه VARIANT ما به این معنی است: وقتی DuckDB یک گروه ردیف را روی دیسک مینویسد، به ستون JSON شما نگاه میکند و فیلدهایی را پیدا میکند که هر بار در بیشتر ردیفها با همان مقدار نشان داده میشوند.
در اینجا یک مثال معمولی وجود دارد، یک رویداد از پنج میلیون:
نوع رویداد همیشه متن است، user.id همیشه یک عدد است، props.amount همیشه اعشاری است. آن زمین ها به ستون های واقعی خود در زیر کاپوت کشیده می شوند. فیلدهای نادر و فیلدهایی که در یک ردیف عددی و در ردیف بعدی متن هستند، در یک باقیمانده باینری با هم می مانند. بنابراین بخش ثابت JSON شما مانند یک جدول معمولی ذخیره میشود و فقط قسمت نامرتب به عنوان یک حباب ذخیره میشود.
مورد کامل سیاهههای مربوط به ساختار است. سطح، سرویس، latency_ms، trace_id در هر خط و همیشه مقدار یکسانی دارند، بنابراین همه آنها خرد می شوند. شی اضافی عجیب و غریب در باقیمانده باقی می ماند، همچنان قابل پرس و جو است، فقط کندتر. تله: تأخیر_ms که در یک خط 231 و در خط بعدی «231 میلیثانیه» است در بقیه نیز میافتد. انواع ارزش ها را ثابت نگه دارید.
VARIANT فقط در مورد سرعت نیست. متن به اندازه CPU در ذخیره سازی حریص است. من پنج میلیون رویداد را گرفتم و همان داده ها را به سه روش ذخیره کردم:
سپس سه پرس و جو در هر کدام: یک فیلتر در دو فیلد، مجموع یک فیلد عددی گروه بندی شده بر اساس کشور، و جستجوی لیست.
بنابراین قانون طلایی مدلینگ هنوز معتبر است: آنچه را که می دانید مدل کنید. فیلدهایی که هر پرس و جو لمس می کند مستحق ستون های واقعی هستند و ارتقای یکی دو عبارت است:
TL;DR: اگر رویدادهای شما مجموعهای ثابت از فیلدها را با انواع ارزش یکسان به اشتراک میگذارند، آنها را بهعنوان VARIANT به جای یک رشته JSON ذخیره کنید. شما یک سوم فضای ذخیره سازی و پرس و جوهای فیلد را دریافت می کنید که مانند ستون های واقعی اجرا می شوند. فیلدهایی را که هر پرس و جو لمس می کند به ستون های واقعی ارتقا دهید، دنباله بلند را در VARIANT نگه دارید و فعلا از ارسال لیست در جستارهای داغ خودداری کنید.
محرک ها هنگامی که ردیف ها تغییر می کنند، جدول به تنهایی کمی از SQL را اجرا می کند. به عنوان مثال، برخی از قیمت ها را به روز کنید، و ماشه هر ردیف را قبل و بعد از تغییر ("جدول انتقال") می بیند و هر دو را در جدول تاریخ می نویسد. پیش از این، هر ابزاری که جدول را لمس می کرد باید به یاد داشته باشد که ردیف تاریخ را در جایی بنویسد. اکنون می توان آن را مستقیما در سمت پایگاه داده انجام داد.
طرحواره های تودرتو: ایجاد SCHEMA finance.reports. و جداول داخل آن
DML در یک CTE: یک DELETE ... RETURNING داخل یک WITH، سپس از آن درج کنید، که الگوی حرکت-ردیف-اتمی است.
Quack، پروتکل سرویس گیرنده-سرور، نیمه دیگر این نسخه است و با آن به نسخه 1.0 می رود. من آن را در ویدیوی خودش پوشش دادم، بنابراین در اینجا آن را تکرار نمی کنم.
آلفا یک خط برای CLI است و سایر مشتریان در صفحه نصب DuckDB هستند:
و البته، MotherDuck نزدیک به انتشار نسخه 2.0 را پشتیبانی خواهد کرد، بنابراین با خیال راحت دست خود را در فضای ابری بگیرید و از تمام قطعاتی که در اینجا در مورد آنها صحبت کردیم لذت ببرید.
Agentic SQL به صورت رایگان با Qwen3.8 27B و DuckDB | اردک مادر
DuckDB 1.5 سریعتر و آسانتر از همیشه است | اردک مادر
بهینه سازی عملکرد پرس و جو | MotherDuck Docs
متن اصلی (انگلیسی)
Why DuckDB 2.0 is faster
Article URL: https://motherduck.com/blog/why-duckdb-20-is-faster/ Comments URL: https://news.ycombinator.com/item?id=50035530 Points: 200 # Comments: 62