SSD Nodes Learn 8GB RAM — ஆண்டுக்கு $66
கல்வி வழிகாட்டிகள் Matt Connorஆல் Matt Connor · புதுப்பிக்கப்பட்டது 2026-08-01

DuckDB vs SQLite server-ல்: எதைப் பயன்படுத்துவது?

SQLite transactional application state-க்கு ஏற்றது; DuckDB Parquet, CSV analytics-க்கு. ஒரே VPS-ல் இரண்டையும் இயக்கும் காரணமும், worked example-களும் இங்கே.

DuckDB vs SQLite on a server: ஒரு வாக்கியப் பதில்

SQLite என்பது OLTP engine (online transaction processing): இது தரவை rows ஆகச் சேமிக்கிறது. ஒரே நேரத்தில் சில rows-ஐப் பாதுகாப்பாகவும் வேகமாகவும் read மற்றும் write செய்வதற்காக இது உருவாக்கப்பட்டுள்ளது. DuckDB என்பது OLAP engine (online analytical processing): இது தரவை columns ஆகச் சேமிக்கிறது. millions of rows-ஐ scan செய்து, ஒரு aggregate-ஐத் திருப்பி வழங்குவதற்காக இது உருவாக்கப்பட்டுள்ளது. இரண்டும் embedded libraries. இரண்டும் ஒரு plain file-ஐத் திறக்கும். இரண்டிற்கும் நீங்கள் தொடர்ந்து கண்காணிக்க வேண்டிய server process தேவையில்லை.

ஆகவே, "எது?" என்ற கேள்விக்கான நேர்மையான பதில் பெரும்பாலும் "இரண்டும், அதே VPS-ல்" என்பதாகும். உங்கள் application-ன் live state SQLite-ல் இருக்கும். உங்கள் reporting, Parquet மற்றும் CSV files-ஐ DuckDB மூலம் படிக்கும். இரண்டும் ஒரே வேலையைச் செய்யாததால், அவை ஒன்றுக்கொன்று போட்டியல்ல.

வரிசை சேமிப்பகமும் நெடுவரிசை சேமிப்பகமும் பதிலை எவ்வாறு மாற்றுகின்றன

SQLite ஒரு வரிசையை page-இன் தொடர்ச்சியான ஒரு பகுதியாக எழுதுகிறது. முதன்மை விசை மூலம் ஒரு order-ஐ பெறும்போது, அது ஒரு index page மற்றும் ஒரு data page-ஐ அணுகுகிறது; ஆகவே இது இரண்டு reads ஆகும். ஒரு application வினாடிக்கு ஆயிரக்கணக்கான முறை செய்யும் செயல் இதுவே: இந்த user-ஐப் படித்தல், இந்த session-ஐப் புதுப்பித்தல், இந்த order-ஐச் செருகுதல்.

DuckDB ஒவ்வொரு column-ஐயும் தனித்தனியாக எழுதி compress செய்கிறது. ஐந்து மில்லியன் rows மீது amount_cents-ஐக் கூட்டும்போது, அது amount_cents column-ஐ மட்டும் படிக்கிறது; file-இல் உள்ள பிற bytes அனைத்தையும் தவிர்க்கிறது; values-இன் batches மீது vectorised code மூலம் கூட்டுத்தொகையை கணக்கிடுகிறது. பிற columns disk-இலிருந்து ஒருபோதும் படிக்கப்படுவதில்லை. வேகம் கிடைப்பதற்கான காரணம் இதுவே.

இப்போது ஒவ்வொரு engine-ஐயும் மற்றொன்றின் workload மீது இயக்கிப் பாருங்கள். SQLite ஒரு column-ஐக் கூட்டும்போது, ஒரு field-ஐ அடைய ஒவ்வொரு row-ஐயும் கடந்து, முழு row-ஐ page-இலிருந்து பெற வேண்டும். எனவே தேவையானதைவிட அதிகமான disk தரவைப் படிக்கிறது. DuckDB ஒரு order-ஐச் செருகும்போது, ஒரே ஒரு value-க்காக ஒவ்வொரு column-இன் storage-ஐயும் அணுக வேண்டும். இதைச் செய்ய அது முழு database file மீது write lock எடுக்கிறது. எந்த engine-மும் பழுதடைந்ததல்ல. ஒவ்வொன்றும் தன்னைச் சார்ந்து வடிவமைக்கப்படாத ஒரு கேள்விக்குப் பதிலளிக்கிறது.

SQLite சிறப்பாகப் பயன்படும் இடம்: transactional application state

Writes சிறியதாகவும் அடிக்கடியாகவும் இருந்து, அவை இழக்கப்படக்கூடாது என்றால் SQLite-ஐத் தேர்ந்தெடுக்கவும். Sessions, orders, queue rows, settings மற்றும் web request உருவாக்கும் எந்தத் தரவும் இதற்கு உட்படும்.

sudo apt update && sudo apt install -y sqlite3
sudo install -d -o "$USER" -g "$USER" /srv/app

அதே படியில் table-ஐ உருவாக்கி, write-ahead logging-ஐ இயக்கவும்.

sqlite3 /srv/app/app.db <<'SQL'
PRAGMA journal_mode = WAL;
CREATE TABLE IF NOT EXISTS orders (
  id           INTEGER PRIMARY KEY,
  customer     TEXT    NOT NULL,
  placed_at    TEXT    NOT NULL,
  amount_cents INTEGER NOT NULL
);
CREATE INDEX IF NOT EXISTS orders_customer ON orders (customer);
INSERT INTO orders (customer, placed_at, amount_cents)
  VALUES ('ana', '2026-07-30T09:14:00Z', 4200);
SQL

வெளியீட்டின் முதல் வரி wal ஆகும். இது mode மாற்றப்பட்டதாகத் தெரிவிக்கும் PRAGMA ஆகும். Server-ல் பயன்படுத்துவதற்கு இது மிகவும் பயனுள்ள setting ஆகும். இயல்புநிலை rollback journal mode-ல், ஒரு writer அனைத்து readers-ஐத் தடுக்கிறது. WAL mode-ல், ஒரு writer புதிய தரவைச் சேர்க்கும் போது readers கடைசியாக commit செய்யப்பட்ட state-ஐத் தொடர்ந்து படிக்க முடியும். எனவே, மெதுவான report அதற்குப் பின்னால் காத்திருக்கும் web request-ஐ இனி தாமதப்படுத்தாது.

Row மீண்டும் கிடைத்ததா என்பதைச் சரிபார்க்கவும்:

sqlite3 /srv/app/app.db "SELECT * FROM orders WHERE customer = 'ana';"

1|ana|2026-07-30T09:14:00Z|4200 கிடைக்கும். Database-ன் அருகில் மேலும் இரண்டு files தோன்றும்: app.db-wal மற்றும் app.db-shm. இவை இரண்டும் அந்த database-க்கு உரியவை. Application இயங்கிக்கொண்டிருக்கும்போது app.db-ஐ மட்டும் copy செய்தால், அது முழுமையற்ற backup ஆகும். இது கீழே மேலும் விளக்கப்பட்டுள்ளது.

SQLite ஒரே நேரத்தில் ஒரு writer-ஐ மட்டுமே அனுமதிக்கிறது. அந்த வரம்பு ஒரு lock; அது queue அல்ல. எனவே, அதிக நேரம் காத்திருக்கும் இரண்டாவது writer, எப்போதும் block ஆகாமல் database is locked என்ற பிழையுடன் தோல்வியடையும். Application திறக்கும் ஒவ்வொரு connection-லும் PRAGMA busy_timeout = 5000;-ஐ அமைத்து wait நேரத்தை அதிகரிக்கவும். சாதாரண web workload-ல் ஐந்து seconds காத்திருப்பு, இந்தப் பிழைகளில் பெரும்பாலானவற்றைத் தவிர்க்கும்.

ஏற்கெனவே உங்களிடம் உள்ள கோப்புகளின் மீதான analytics-இல் DuckDB சிறப்பாக செயல்படும் இடம்

கேள்வி "எத்தனை", "எவ்வளவு" அல்லது "முதல் பத்து எவை" என்று தொடங்கும்போது, input என்பது CSV அல்லது Parquet கோப்புகளின் தொகுப்பாக இருக்கும்போது DuckDB-ஐத் தேர்ந்தெடுக்கவும். command line client-ஐ install செய்யவும். July 2026 நிலவரப்படி version 1.5.5:

curl https://install.duckdb.org | sh

இந்த script binary-ஐ ~/.duckdb/cli/latest/duckdb இன் கீழ் install செய்து, அதை உங்கள் PATH இல் சேர்க்கும் வரியை அச்சிடும். இது இயங்குகிறதா என்பதை உறுதிப்படுத்தவும்:

~/.duckdb/cli/latest/duckdb :memory: "SELECT version();"

வினவுவதற்கான யதார்த்தமான கோப்பை உருவாக்கவும். இது zstd compression பயன்படுத்தி, orders-ன் ஐந்து million rows-ஐ Parquet-க்கு எழுதும்:

mkdir -p /srv/data
duckdb :memory: "
COPY (
  SELECT i                                                     AS id,
         'cust_' || (i % 5000)                                 AS customer,
         TIMESTAMP '2026-01-01 00:00:00' + INTERVAL (i) MINUTE AS placed_at,
         (i * 37) % 20000                                      AS amount_cents
  FROM range(5000000) t(i)
) TO '/srv/data/orders.parquet' (FORMAT parquet, COMPRESSION zstd);"

இப்போது analytical கேள்வியைக் கேட்கவும். shell-ஐத் திறந்து, timer-ஐ இயக்கி, எந்த import படியும் இல்லாமல் கோப்பை நேரடியாக query செய்யவும்:

.timer on
SELECT customer,
       count(*)                AS orders,
       sum(amount_cents)/100.0 AS revenue
FROM '/srv/data/orders.parquet'
GROUP BY customer
ORDER BY revenue DESC
LIMIT 5;

வெளியிடப்பட்ட எண்ணை நம்புவதற்குப் பதிலாக, உங்கள் சொந்த எண்ணை .timer இலிருந்து படிக்கவும். காரணம், முடிவு உங்கள் disk மற்றும் core count-ஐப் பொறுத்தது. எண்ணின் வடிவமே முக்கியம். CREATE TABLE இல்லை, INSERT இல்லை, load படியும் இல்லை: DuckDB Parquet footer-ஐப் படித்து, query-க்குத் தேவையான column chunks எவை என்பதைத் தீர்மானித்து, அவற்றை மட்டும் படித்தது. முழு directory-க்கும் glob, FROM '/srv/data/orders-*.parquet', பயன்படுத்தினால் இதேபோல் செயல்படும். இதன் மூலம் ஒரு மாதத்தின் daily exports ஒரே query-ஆக மாறும்.

இவை அனைத்திற்கும் அடிப்படையாக disk speed உள்ளது. Column scan என்பது நீண்ட sequential read ஆகும். ஆகவே, VPS-இல் NVMe மற்றும் பழைய SATA storage-க்கு இடையிலான வேறுபாடு SQLite-ன் சிறிய random reads-இல் தெரியாத அளவுக்கு இங்கு தெளிவாகத் தெரியும்.

DuckDB இலிருந்து உங்கள் SQLite database-ஐப் படித்தல்

இரண்டு engines-ம் DuckDB-ன் sqlite extension மூலம் இணைகின்றன. Analytics query இயங்கும் live state-இல் ஒருபோதும் எழுத முடியாதபடி, application database-ஐ read only முறையில் attach செய்யவும்:

INSTALL sqlite;
LOAD sqlite;
ATTACH '/srv/app/app.db' AS app (TYPE sqlite, READ_ONLY);
SELECT customer, count(*) AS orders
FROM app.orders
GROUP BY customer
ORDER BY orders DESC;

இது copy எதையும் உருவாக்காமல், query இயங்கும் நேரத்தில் SQLite file-இலிருந்து rows-ஐப் படிக்கிறது. இது வசதியானது, ஆனால் வேகமானது அல்ல. Disk-இல் உள்ள data இன்னும் row storage ஆகவே இருப்பதால், DuckDB அதனை முழுமையாகப் படிக்க வேண்டும். இதை export-க்குப் பயன்படுத்தவும். ஒவ்வொரு முப்பது விநாடிகளுக்கும் reload செய்யும் dashboard-க்கு இதைப் பயன்படுத்த வேண்டாம்:

COPY (SELECT * FROM app.orders)
  TO '/srv/data/orders-2026-07.parquet' (FORMAT parquet, COMPRESSION zstd);

அந்த ஒரு statement-தான் முழு pattern. SQLite சமீபத்திய live rows-ஐ நிர்வகிக்கிறது. Scheduled export, முடிவடைந்த காலப்பகுதிகளை Parquet ஆக மாற்றுகிறது. பல மாதங்களை உள்ளடக்கும் ஒவ்வொரு கேள்விக்கும் DuckDB பதிலளிக்கிறது. Application database சிறியதாகவே இருக்கும். இதனால் அதன் writes வேகமாக இருக்கும்.

Export-ஐ கையால் இயக்காமல், schedule-இல் இயக்கவும். இதற்கு systemd service மற்றும் timer இணைப்பு பொருத்தமானது: ஒன்று COPY-ஐ இயக்கும் unit, மற்றொன்று அதனை ஒவ்வொரு இரவும் இயக்கும் timer.

ஒரே VPS-இல் இரண்டையும் இயக்குதல்

இங்கே எதற்கும் container தேவையில்லை; port-உம் தேவையில்லை. இரண்டு engines-உம் libraries ஆகும். எனவே installation என்பது ஒரு package மற்றும் ஒரு file path ஆகியவற்றைக் கொண்டது. உங்கள் stack-இன் மீதிப் பகுதிகள் ஏற்கனவே அதே VPS-இல் Docker Compose கீழ் இயங்கினால், database service-ஐச் சேர்ப்பதற்குப் பதிலாக, தேவைப்படும் container-இல் data directory-ஐ mount செய்யுங்கள். சேர்க்கக்கூடிய service எதுவும் இல்லை.

இந்த அமைப்பு சிக்கலின்றி இயங்க இரண்டு விதிகள் உதவும்.

ஒவ்வொரு engine-க்கும் தனித்தனி directory வழங்குங்கள்: application எழுதும் SQLite file-க்கு /srv/app, analytics படிக்கும் Parquet files-க்கு /srv/data. இரண்டும் ஒரே directory-ஐப் பகிர்ந்தால், ஒன்றின் snapshot-ஐ எடுக்கும் backup job மற்றொன்றுடன் ஒரே நேரத்தில் இயங்கிப் போட்டியிடும்.

இரண்டு processes-ஐ ஒரே DuckDB database file-ஐ read-write mode-இல் பயன்படுத்துமாறு அமைக்க வேண்டாம். ஒரே ஒரு process மட்டுமே DuckDB file-ஐ எழுதுவதற்காகத் திறந்து வைத்திருக்கலாம். இரண்டாவது process அந்த file-ஐத் திறக்கவே முடியாது. ஒவ்வொரு process-உம் access_mode = 'READ_ONLY'-ஐ அமைத்திருந்தால், பல readers இயங்கலாம். SQLite-இலிருந்து வருபவர்களுக்கு இது எதிர்பாராததாக இருக்கும். SQLite-இல் பல processes ஒரு file-ஐ வழக்கமாகப் பகிர்ந்து பயன்படுத்துகின்றன. உங்கள் analytics Parquet files-ஐ மட்டுமே படித்தால், இந்தச் சிக்கல் ஏற்படாது. இதனால் durable state-ஐ SQLite-இல் வைத்திருப்பதற்கான மேலும் ஒரு காரணம் கிடைக்கிறது.

காப்புப்பிரதிகள் வேறுபடும்; அந்த வேறுபாடு சிக்கலை ஏற்படுத்தும்

இயங்கும் SQLite database மூன்று files-ஆக இருக்கும். எழுதும் பணியின் நடுவில் cp மூலம் அவற்றை copy செய்தால், திறக்கக்கூடியதாக இருந்தாலும் தவறான file கிடைக்கும். Application தொடர்ந்து எழுதிக்கொண்டிருக்கும்போது consistent snapshot-ஐ உருவாக்கும் database engine-ன் சொந்த backup command-ஐப் பயன்படுத்தவும்:

sqlite3 /srv/app/app.db ".backup '/srv/backup/app-$(date -u +%Y%m%dT%H%M%SZ).db'"
sqlite3 /srv/backup/app-20260730T091400Z.db "PRAGMA integrity_check;"

சரியான copy-க்கு integrity_check, ok என்பதை output ஆகக் காட்டும். வேறு எதுவாக இருந்தாலும், அந்த snapshot-ஐ நீக்கிவிட்டு மீண்டும் எடுக்க வேண்டும்.

Parquet files எழுதப்பட்ட பிறகு ஒருபோதும் மாறாது. எனவே அவற்றுக்கு சிறப்பு handling தேவையில்லை; directory-ஐ backup செய்யவும். உங்கள் VPS-இலிருந்து restic backups மூலம் இரண்டு paths-ஐயும் server-க்கு வெளியே அனுப்பவும். இதனால் முழு data layer-மும் ஒரே backup job-இல் இரண்டு directories ஆக இருக்கும்.

தோல்வி நிலைகள் மற்றும் நீங்கள் காணும் துல்லியமான சரங்கள்

SQLite வழங்கும் Error: database is locked, மற்றொரு connection உங்கள் timeout அனுமதித்த காலத்தைவிட நீண்ட நேரம் write lock-ஐ வைத்திருந்தது என்பதைக் குறிக்கிறது. இது corruption அல்ல. ஒவ்வொரு connection-லும் PRAGMA busy_timeout அமைக்கவும். பின்னர், பல குறுகிய transaction-களாக இருந்திருக்க வேண்டிய நீண்ட transaction எது என்பதைத் தேடவும்.

Permission மாற்றத்திற்குப் பிறகு தோன்றும் Error: unable to open database file, process file-ஐ write செய்ய முடிகிறது, ஆனால் அதன் directory-யில் write செய்ய முடியவில்லை என்பதைக் குறிக்கிறது. SQLite, database-க்கு அருகில் app.db-wal மற்றும் app.db-shm ஆகியவற்றை உருவாக்குகிறது. எனவே .db file மட்டும் அல்லாமல் directory-யும் writable ஆக இருக்க வேண்டும்.

DuckDB வழங்கும் IO Error: Could not set lock on file, மற்றொரு process அந்த database-ஐ ஏற்கனவே writing-க்காக open செய்துள்ளது என்பதைக் குறிக்கிறது. மற்ற shell-ஐ close செய்யவும் அல்லது உங்கள் shell-ஐ read only முறையில் open செய்யவும்.

சிறிய VPS-ல் DuckDB வழங்கும் Out of Memory Error, query-க்கு கிடைத்த working memory-யைவிட அதிக memory தேவைப்பட்டது என்பதைக் குறிக்கிறது. முடிந்தால் DuckDB, data-வை disk-க்கு spill செய்கிறது. எனவே :memory:-க்கு பதிலாக disk-ல் உள்ள database file-ஐ open செய்வதன் மூலம் spill செய்ய இடம் வழங்கவும். மேலும் SET memory_limit = '2GB'; மூலம் அதன் memory பயன்பாட்டிற்கு வரம்பு அமைக்கவும். பிற services இயங்கும் server-ல், ad hoc query உங்கள் application-ஐ RAM-இலிருந்து வெளியேற்றுவதைத் தடுப்பது இந்த வரம்பாகும்.

Parquet-ஐ query செய்யும்போது தோன்றும் Binder Error: Referenced column "amount" not found, file-ன் schema நீங்கள் நினைவில் வைத்திருப்பதல்ல என்பதையே பெரும்பாலும் குறிக்கிறது. DESCRIBE SELECT * FROM '/srv/data/orders.parquet'; இயக்கி, உண்மையான column names-ஐப் பெறவும்.

நடைமுறையில் எதைத் தேர்வு செய்வது

எழுதும் முறை என்ன என்பதை முதலில் கேளுங்கள். மின்தடை ஏற்பட்டாலும் நிலைத்திருக்க வேண்டிய பல சிறிய write செயல்பாடுகள் இருந்தால், SQLite-ஐத் தேர்வு செய்யுங்கள். படிக்கும் முறை என்ன என்பதையும் கேளுங்கள். நீண்டகால வரலாற்றுத் தரவின் மீது aggregate செயல்பாடுகளுடன் full scan தேவைப்பட்டால், DuckDB-ஐத் தேர்வு செய்யுங்கள். பெரும்பாலான உண்மையான systems இந்த இரண்டு கேள்விகளுக்கும் ஆம் என்று பதிலளிக்கும். அப்போது, ஒரு engine மற்றொன்றின் பணியையும் செய்யுமாறு கட்டாயப்படுத்துவதற்குப் பதிலாக, ஒவ்வொரு engine-க்கும் அது சிறப்பாகச் செய்யும் பாதியை வழங்குவதே சரியான அணுகுமுறை.

தவிர்க்க வேண்டிய migration என்பது, ஒரு report மெதுவாக இருந்ததால் live application state-ஐ DuckDB-க்கு மாற்றுவதாகும். Storage layout காரணமாகவே report மெதுவாக இருந்தது. எனவே தீர்வு export செய்வதே; உங்கள் write path-ஐ மறுபடியும் எழுதுவது அல்ல.

FAQ

DuckDB என் application database-க்கு SQLite-ஐ மாற்ற முடியுமா?

அடிக்கடி write செய்யும் database-க்கு முடியாது. DuckDB முழு database file-க்கும் write lock விதிக்கிறது. ஒரே நேரத்தில் ஒரு read-write process-ஐ மட்டுமே அனுமதிக்கிறது. இது single-row inserts-க்குப் பதிலாக bulk changes-க்காகச் சிறப்பாக வடிவமைக்கப்பட்டுள்ளது. Transactional state-ஐ SQLite-ல் வைத்திருங்கள். Report தேவைப்படும் போது, ATTACH '/srv/app/app.db' AS app (TYPE sqlite, READ_ONLY); மூலம் DuckDB அதை read செய்ய அனுமதியுங்கள்.

Analytics-க்கு DuckDB உண்மையில் SQLite-ஐவிட வேகமானதா?

பெரிய table-ல் scans மற்றும் aggregates செய்யும்போது, ஆம். இதற்கான காரணம் tuning trick அல்ல, storage layout ஆகும். Query குறிப்பிடும் columns-ஐ மட்டும் DuckDB read செய்து, values-ஐ batches-ஆக process செய்கிறது. ஆனால் SQLite ஒரு field-ஐ அடைய முழு rows-ஐயும் கடக்க வேண்டும். Primary key மூலம் ஒரு row-ஐ மட்டும் பெறும்போது முடிவு மாறுகிறது. SQLite இரண்டு pages-ஐத் தொடும். DuckDB ஒவ்வொரு column-ன் storage-ஐயும் தொடும்.

VPS-ல் DuckDB-ஐ இயக்க அதிக RAM தேவைப்படுமா?

தேவைப்படாது. ஆனால் அதற்கு ஒரு limit மற்றும் disk வழங்குங்கள். :memory:-க்கு பதிலாக database file-ஐ open செய்யுங்கள். இதனால் DuckDB intermediate results-ஐ disk-க்கு spill செய்ய முடியும். பின்னர் உங்கள் VPS ஒதுக்கக்கூடிய அளவுக்கு SET memory_limit = '2GB';-ஐ அமைக்கவும். Limit இல்லையெனில், ஒரு பெரிய GROUP BY Out of Memory Error-ஐ உயர்த்தலாம் அல்லது பிற services-ஐ RAM-இலிருந்து வெளியேற்றலாம்.

SQLite data-ஐ Parquet-க்கு எவ்வாறு மாற்றுவது?

DuckDB-லிருந்து SQLite file-ஐ attach செய்து, COPY (SELECT * FROM app.orders) TO '/srv/data/orders.parquet' (FORMAT parquet, COMPRESSION zstd); மூலம் query-யை நேரடியாக copy செய்யுங்கள். கடந்த மாதத்தின் rows போன்ற மூடப்பட்ட காலப்பகுதிகளுக்கு இதை schedule-ல் இயக்குங்கள். Application இன்னும் write செய்யும் recent rows-ஐ SQLite-ல் வைத்திருங்கள்.

எதை backup செய்ய வேண்டும், எவ்வாறு செய்ய வேண்டும்?

இரண்டையும், வெவ்வேறு முறைகளில் backup செய்ய வேண்டும். cp-க்கு பதிலாக sqlite3 app.db ".backup '/srv/backup/app.db'" மூலம் SQLite snapshots எடுக்கவும். ஏனெனில் இயங்கும் database ஒரு -wal மற்றும் -shm file ஆகவும் இருக்கும்; plain copy துண்டிக்கப்பட்ட நிலையில் இருக்கலாம். Parquet files எழுதப்பட்ட பிறகு ஒருபோதும் மாறாது. ஆகவே directory-ஐ copy செய்வது போதுமானது.

#duckdb#sqlite#database#analytics#parquet#self-hosting