DuckDB или SQLite: бързата база зависи от формата на заявката

|Автор: Редакционният екип на QUASA|5 мин. четене
DuckDB или SQLite: бързата база зависи от формата на заявката

SQLite е подходящият избор, когато приложението най-често намира отделни записи по индекс и извършва кратки транзакции. DuckDB има предимство, когато заявките обхождат голяма част от данните, свързват множество редове и изчисляват обобщения. Една и съща таблица може да даде различен победител според това кои редове трябва да бъдат обработени.

При смесено натоварване двете бази могат да имат различни роли: SQLite да обслужва текущите записи, а DuckDB да изпълнява анализа. Това позволява изборът на аналитичен инструмент да се разгледа отделно от решението къде приложението съхранява данните си.

Индексът печели при точково търсене

Точково търсене на едно пътуване в транспортните данни GTFS, при което индексът дава предимство на SQLite.

В теста на Лукас Барт с германски транспортни данни търсенето на пътуване по първичен ключ отнема средно 0,063 ms в SQLite срещу 0,927 ms в DuckDB, или 14,7 пъти по-малко време; при неиндексирана заявка, която избира приблизително половината пътувания, DuckDB отчита 2,90 ms срещу 2722 ms за SQLite, или преднина от 938,6 пъти. За двете бази са създадени индекси, а времената са измерени след първоначално изпълнение за затопляне на кеша. Резултатите описват конкретните данни, заявки и версии от теста.

Точковото търсене започва с известен идентификатор и трябва да достигне до малко редове. В този случай достъпът през подходящ индекс спестява обхождането на таблицата. Широката заявка в същия тест филтрира по поле без индекс и връща голям дял от пътуванията. Тогава базата трябва да обработи много редове, а предимството на бързото намиране на един запис вече не определя общото време.

Тестът включва и JOIN между таблиците за пътувания и спирки, но условието посочва конкретно пътуване и конкретна поредна спирка. Това е селективно свързване, близко до точковото търсене по обем на резултата. JOIN между големи множества, последван от групиране, поставя друга задача: цената зависи от броя обработени редове и от работата след свързването, а не от самото присъствие на JOIN в заявката.

Агрегациите и малките транзакции сменят подредбата

Аналитична агрегация в Star Schema Benchmark, която свързва голяма таблица с факти с четири таблици с измерения.

В изследването „SQLite: Past, Present, and Future“ DuckDB изпълнява по-бързо всички измерени аналитични заявки от Star Schema Benchmark, докато при транзакционния TATP на облачен сървър SQLite в режим WAL постига 10 пъти по-висока пропускателна способност при малката база и 500 пъти при голямата. Измерванията сравняват пропускателна способност при транзакциите и време за изпълнение при аналитичните заявки — различни показатели за различна работа.

Star Schema Benchmark използва голяма таблица с факти и по-малки таблици с измерения. Заявките свързват данните, филтрират ги и изчисляват резултати върху значителен обем записи. Колонната организация и векторното изпълнение на DuckDB са предназначени за такава обработка. Индексът може да помогне и при JOIN, но ако свързването трябва да премине през множество редове и да ги обобщи, бързото достигане до един ред не решава цялата задача.

TATP има друг ритъм: кратки операции с четене и промени по отделни записи. Затова резултатът му е по-близък до натоварването на приложение, което постоянно приема малки транзакции, отколкото до периодичен отчет върху цяла таблица. Предимството в този тест принадлежи на измерената конфигурация SQLite с WAL. То не е обещание за същото съотношение при различен режим на журнал, хардуер или състав на транзакциите.

Една таблица, пет различни задачи

За да се види защо изборът се обръща, може да се започне от една таблица с пътувания и да се сменя само работата, която заявката изисква. Документацията за планиране на заявки в SQLite обяснява как индексът насочва търсенето към съответните записи и защо редът на колоните в съставния индекс има значение. Това е механизъм за ограничаване на търсенето, а не общо ускорение за всяка заявка към таблицата.

  • Точково търсене: условие по идентификатор на пътуване намира малък резултат. Подходящият индекс и времето за отговор на единичната заявка са решаващи; това е сценарият, в който SQLite води в транспортния тест.
  • JOIN: свързване на конкретно пътуване със спирката му остава селективна заявка. Свързване на много пътувания с други записи преди групиране увеличава обема работа, дори SQL операторът да е същият.
  • Широко сканиране: условие, което няма използваем индекс и избира голяма част от пътуванията, изисква обхождане на множество редове. Тук транспортният тест показва голяма преднина за DuckDB.
  • Агрегации: ако целта е обобщение по маршрут, период или друга характеристика върху много записи, важна става скоростта на обработка на цялото множество. Това е типът работа, представен от аналитичния тест.
  • Записи: добавяне и промяна на отделни пътувания създава поток от кратки транзакции. За него показателна е пропускателната способност при транзакционно натоварване, а не времето за аналитичен отчет.

Това разграничение пази и от привидно справедливо сравнение: бързо извличане на един ред и бързо обобщаване на цяла таблица не измерват едно и също свойство. Също така скоростта на единична заявка не е равнозначна на броя транзакции, които базата обработва последователно. Приложение с чести записи и редки отчети може да даде различен практически приоритет от инструмент, който предимно анализира вече събрани данни.

Анализ върху SQLite без пълна миграция

DuckDB чете съществуващ SQLite файл за анализ, докато приложението запазва транзакционния си път към същата база.

Официалната документация на SQLite разширението за DuckDB описва прикачване на SQLite файл чрез ATTACH, директно четене на таблиците и възможност за промени в тях. Така приложението може да продължи да записва в SQLite, докато отделен аналитичен път използва DuckDB върху съществуващите данни. Не е необходимо цялата база първо да се премести в собствен файл на DuckDB.

Прикачването обаче запазва SQLite като хранилище: таблиците се четат от неговия файл по време на заявката. Следователно резултатите от тестове със собственото хранилище на DuckDB не се пренасят автоматично върху директното четене през разширението. Ако едни и същи тежки отчети се изпълняват често, отделно аналитично копие може да ускори тази работа, но тогава възниква и задължението то да се поддържа актуално.

Конкурентният достъп също следва правилата за заключване на SQLite: множество читатели могат да работят едновременно, докато записите се извършват последователно. Хибридният модел е най-смислен, когато разделя действително различни натоварвания — кратките промени остават по транзакционния път, а широките аналитични заявки получават собствен изпълнител. Колко ще спечели аналитичният път зависи от това дали чете директно SQLite файла или данни, заредени в DuckDB.

Прочетете също:

Споделяне:

Абонирайте се за нашия бюлетин

Получавайте най-новите новини за Web3, AI и криптовалути директно във входящата си поща.

0