DuckDB анонсировала 2.0: серверный режим, триггеры и ускорение до 40 раз

Команда DuckDB, открытой аналитической базы данных, изначально работавшей только «в процессе» (встроенной прямо в приложение), опубликовала в блоге проекта предпросмотр версии 2.0, релиз которой запланирован на эту осень. Версия получит кодовое имя Cyanoptera, в честь чирка коричневокрылого (Anas cyanoptera), краснокоричневой утки, обитающей на западе Америки. За релизом стоит больше 10 000 коммитов, накопленных с выхода предыдущей крупной версии, 1.5 в марте.
Главное новшество, серверный режим. Раньше DuckDB работал только как встроенная в процесс библиотека; теперь расширение quack, ранее доступное как превью, переходит в стабильный статус и реализует собственный сетевой протокол DuckDB. Один процесс DuckDB может обслуживать свои базы по сети, а другой, подключаться к нему новой командой CONNECT и выполнять запросы удалённо, получая результат потоком; для отключения служит DISCONNECT. Новый оптимизатор удалённого проброса запросов идёт дальше: CONNECT работает не только с другими DuckDB, но и с PostgreSQL и MySQL, запрос в этом случае выполняется прямо на удалённом сервере, а не тянет таблицы целиком по сети. Разработчики подчёркивают, что DuckDB с самого начала был транзакционной базой с полной поддержкой MVCC и изоляции транзакций, просто эта возможность обычно не требовалась в однопользовательском сценарии; серверный режим наконец даёт этой машинерии применение в многопользовательских и долгоживущих развёртываниях. Для таких инстансов версия 2.0 также добавляет более развитые метрики, логи и наблюдаемость.
Тип VARIANT, появившийся ещё в версии 1.5, становится полноценным гражданином языка, его описывают как «JSON, но если бы он был быстрым»: в отличие от JSON это не текстовый формат, DuckDB автоматически распознаёт общую структуру полуструктурированных данных и «расщепляет» её для компактного хранения и быстрого выполнения запросов без объявления схемы заранее. Это удобно для потокового приёма логов, где записи в формате JSON имеют общую, но меняющуюся со временем структуру. В версии 2.0 весь конвейер работает целиком: расщеплённое выполнение прямо из хранилища, проброс операций извлечения в сканирование, чтение и запись расщеплённого VARIANT для формата Parquet, а также набор функций variant_*. В перспективе, вероятно вскоре после выхода 2.0 (но команда не даёт твёрдых обещаний), обычный тип JSON планируют сделать основанным на VARIANT, чтобы существующие запросы получили все эти преимущества без изменений в коде.
Впервые в DuckDB появляются триггеры: BEFORE и AFTER, для каждой строки и для каждого оператора, таблицы перехода через REFERENCING OLD/NEW TABLE, несколько триггеров на одно событие, RETURNING на таблицах с триггерами и DROP TRIGGER. Классический пример применения, таблицы аудита, куда триггер записывает, что именно изменилось.
Диалект SQL расширяется рядом новых возможностей: джойны NEAREST для поиска top-k по схожести (пригодится для векторных и эмбеддинг-нагрузок); операции изменения данных INSERT/UPDATE/DELETE/COPY прямо внутри CTE; вложенные схемы (схема внутри схемы); новый синтаксис переменных, $x можно подставлять прямо в выражение вместо громоздкого getvariable(...); функции для изменения JSON-документов на месте (json_set, json_insert, json_replace, json_remove); и рекурсивные CTE с агрегацией USING KEY, опирающиеся на переписанный движок рекурсивных CTE.
Отдельный крупный блок изменений, производительность. DuckDB добавляет асинхронный ввод-вывод по всему движку: слой ввода-вывода теперь масштабируется независимо от слоя обработки запросов, что даёт заметно больший параллелизм при чтении с сетевых хранилищ вроде S3, сначала для Parquet, затем для CSV и собственного формата файлов DuckDB, плюс асинхронная запись Parquet и новые режимы MMAP и DIRECT_IO; локальное хранилище тоже выигрывает, но, по словам разработчиков, основной прирост, именно на сетевых хранилищах. На микробенчмарке с рекурсивным CTE, поиском достижимости в графе на миллион рёбер, который можно запустить на обычном ноутбуке, версия 2.0 оказалась примерно в 40 раз быстрее прежней версии на том же запросе; Windows CLI при многопоточной материализации результатов ускорился примерно в 2,2 раза. Также расширено отсечение групп строк: min-max индексы и Bloom-фильтры Parquet теперь пропускают данные для структур, списков, decimal, UUID, IN-фильтров и даже предикатов-функций; планирование запросов стало учитывать партиционирование данных, для DuckLake, Iceberg и Parquet, партиционированного по схеме Hive на S3.
Версия формата хранения по умолчанию повышается до v2.0.0: главное изменение, буферизованные ART-индексы, которые больше не закрепляются целиком в памяти, поэтому большие индексированные таблицы открываются мгновенно, а индексы подгружаются по требованию. Метаданные столбцов теперь загружаются лениво, так что и широкие таблицы открываются быстрее; по умолчанию включено сжатие строк методом DICT_FSST, удаления хранятся компактнее, а слой хранения строже проверяет данные на повреждения.
Наконец, DuckDB отказывается от парсера SQL, унаследованного от PostgreSQL, в пользу собственного PEG-парсера с поддержкой расширений: он позволяет сторонним расширениям встраиваться прямо в грамматику языка, что открывает дорогу расширениям с совершенно новым SQL-синтаксисом, даёт более точные сообщения об ошибках с указанием места в запросе и первый режим совместимости с диалектом другой СУБД (dialect_compatibility_mode = 'spark'). Разработчики утверждают, что пользователи не должны заметить замену парсера, поскольку он спроектирован совместимым со старым.
Ключевые факты
- Релиз DuckDB v2.0 запланирован на эту осень, кодовое имя Cyanoptera; в основе, свыше 10 000 коммитов с выхода версии 1.5 в марте.
- Впервые появляется серверный режим: расширение quack и команда CONNECT позволяют одному DuckDB подключаться к другому по сети, а новый оптимизатор проброса запросов передаёт SQL напрямую в PostgreSQL и MySQL.
- Тип VARIANT становится полноценным, «JSON, но быстрый», с автоматическим расщеплением структуры для хранения и запросов без объявления схемы; впервые появляются триггеры (BEFORE/AFTER, таблицы перехода OLD/NEW).
- Новый SQL-парсер на основе PEG заменяет унаследованный от PostgreSQL, формат хранения обновлён до v2.0.0 с буферизованными ART-индексами, добавлен асинхронный ввод-вывод.
- На микробенчмарке с рекурсивным CTE на графе из миллиона рёбер версия 2.0 показала ускорение примерно в 40 раз; Windows CLI при материализации результатов ускорился примерно в 2,2 раза.
Почему это важно
DuckDB, одна из самых распространённых встраиваемых аналитических баз данных, и версия 2.0, редкий для проекта случай сознательного слома совместимости: новый парсер SQL, новый формат хранения по умолчанию, переработанный C API и, главное, первый в истории DuckDB серверный/клиентский режим. Это переводит DuckDB из чисто встроенной библиотеки в инструмент, который может работать как долгоживущий сетевой сервис для многих пользователей одновременно, раньше для этого приходилось использовать обходные пути вроде синтаксиса remote.query(), от которого команда прямо отказалась в пользу CONNECT.
Кому это важно
Инженерам данных и разработчикам, которые уже используют DuckDB в аналитических и lakehouse-пайплайнах (DuckLake, Iceberg, партиционированный Parquet на S3) и хотят перейти к многопользовательским, долгоживущим развёртываниям вместо разового встраивания в один процесс. Также, тем, кто работает с потоковыми JSON-подобными логами и выиграет от VARIANT, командам, которым нужны триггеры для аудита изменений, и авторам расширений DuckDB, для которых новый PEG-парсер открывает возможность встраиваться прямо в грамматику языка.
Как это применить
Пока это предпросмотр, а не финальный релиз, сама DuckDB называет выход версии «этой осенью», без точной даты. Расширение quack для серверного режима уже существовало как превью до этого поста и в 2.0 переходит в стабильный статус, так что попробовать связку quack/CONNECT, VARIANT-функции и триггеры можно будет по мере выхода промежуточных сборок. Отдельно стоит обратить внимание на новый параметр dialect_compatibility_mode = 'spark', первый режим совместимости диалекта, и на новый синтаксис переменных $x, упрощающий параметризованные запросы. Данных о цене, лицензии или условиях доступа к серверному режиму в источнике нет.
Можно ли доверять
Источник, официальный блог самого проекта DuckDB, то есть это самоописание разработчиков ещё не вышедшего релиза, а не независимый обзор. Цифры ускорения (40× и 2,2×), собственные бенчмарки команды; при этом микробенчмарк с рекурсивным CTE описан достаточно подробно и явно предлагается как воспроизводимый, читатель может запустить его сам на обычном ноутбуке. На Hacker News пост набрал 574 балла и 104 комментария, то есть попал под активное обсуждение сообщества, но само обсуждение здесь не пересказывается.
Риски и подводные камни
В одном релизе сознательно совмещены сразу несколько несовместимых с прошлым изменений: новый SQL-парсер, новый формат хранения по умолчанию и переработанный C API, миграция может задеть существующий код и данные. Обещание «пользователи не должны заметить замену парсера», собственное утверждение разработчиков, ничем внешним не подтверждённое. Планы сделать обычный JSON основанным на VARIANT прямо оговорены как необязательные («don't hold us to it», не воспринимайте это как обещание). Цифры ускорения получены на одном конкретном микробенчмарке (граф на миллион рёбер, один ноутбук) и не обязаны переноситься на все рабочие нагрузки. Год релиза («этой осенью») и год выхода версии 1.5 («в марте») в источнике не указаны.
«На самом деле вы не должны заметить ничего от замены парсера, мы спроектировали его совместимым со старым.»
— команда DuckDB, блог проекта DuckDB