mergendb 0.1.0__tar.gz
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- mergendb-0.1.0/LICENSE +21 -0
- mergendb-0.1.0/PKG-INFO +293 -0
- mergendb-0.1.0/README.md +261 -0
- mergendb-0.1.0/mergendb/__init__.py +28 -0
- mergendb-0.1.0/mergendb/cli/repl.py +160 -0
- mergendb-0.1.0/mergendb/client.py +134 -0
- mergendb-0.1.0/mergendb/compression/__init__.py +4 -0
- mergendb-0.1.0/mergendb/compression/compressor.py +146 -0
- mergendb-0.1.0/mergendb/compression/encodings.py +335 -0
- mergendb-0.1.0/mergendb/core/__init__.py +14 -0
- mergendb-0.1.0/mergendb/core/block.py +109 -0
- mergendb-0.1.0/mergendb/core/schema.py +57 -0
- mergendb-0.1.0/mergendb/core/types.py +53 -0
- mergendb-0.1.0/mergendb/io/__init__.py +3 -0
- mergendb-0.1.0/mergendb/io/importer.py +290 -0
- mergendb-0.1.0/mergendb/query/__init__.py +31 -0
- mergendb-0.1.0/mergendb/query/ast_nodes.py +69 -0
- mergendb-0.1.0/mergendb/query/engine.py +332 -0
- mergendb-0.1.0/mergendb/query/lexer.py +241 -0
- mergendb-0.1.0/mergendb/query/parser.py +254 -0
- mergendb-0.1.0/mergendb/query/planner.py +87 -0
- mergendb-0.1.0/mergendb/storage/__init__.py +13 -0
- mergendb-0.1.0/mergendb/storage/format.py +6 -0
- mergendb-0.1.0/mergendb/storage/reader.py +145 -0
- mergendb-0.1.0/mergendb/storage/writer.py +139 -0
- mergendb-0.1.0/mergendb.egg-info/PKG-INFO +293 -0
- mergendb-0.1.0/mergendb.egg-info/SOURCES.txt +35 -0
- mergendb-0.1.0/mergendb.egg-info/dependency_links.txt +1 -0
- mergendb-0.1.0/mergendb.egg-info/entry_points.txt +2 -0
- mergendb-0.1.0/mergendb.egg-info/top_level.txt +1 -0
- mergendb-0.1.0/pyproject.toml +57 -0
- mergendb-0.1.0/setup.cfg +4 -0
- mergendb-0.1.0/setup.py +39 -0
- mergendb-0.1.0/tests/test_compression.py +74 -0
- mergendb-0.1.0/tests/test_importer.py +101 -0
- mergendb-0.1.0/tests/test_query_engine.py +99 -0
- mergendb-0.1.0/tests/test_storage.py +75 -0
mergendb-0.1.0/LICENSE
ADDED
|
@@ -0,0 +1,21 @@
|
|
|
1
|
+
MIT License
|
|
2
|
+
|
|
3
|
+
Copyright (c) 2026 Uğur Türker Kebeci (ugurturkerkebeci)
|
|
4
|
+
|
|
5
|
+
Permission is hereby granted, free of charge, to any person obtaining a copy
|
|
6
|
+
of this software and associated documentation files (the "Software"), to deal
|
|
7
|
+
in the Software without restriction, including without limitation the rights
|
|
8
|
+
to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
|
|
9
|
+
copies of the Software, and to permit persons to whom the Software is
|
|
10
|
+
furnished to do so, subject to the following conditions:
|
|
11
|
+
|
|
12
|
+
The above copyright notice and this permission notice shall be included in all
|
|
13
|
+
copies or substantial portions of the Software.
|
|
14
|
+
|
|
15
|
+
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
|
16
|
+
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
|
17
|
+
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
|
|
18
|
+
AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
|
19
|
+
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
|
|
20
|
+
OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
|
|
21
|
+
SOFTWARE.
|
mergendb-0.1.0/PKG-INFO
ADDED
|
@@ -0,0 +1,293 @@
|
|
|
1
|
+
Metadata-Version: 2.1
|
|
2
|
+
Name: mergendb
|
|
3
|
+
Version: 0.1.0
|
|
4
|
+
Summary: Ultra-compact, columnar, embedded database engine and custom query language (MergenQL) designed to run large workloads on small hardware.
|
|
5
|
+
Home-page: https://github.com/ugurturkerkebeci/MergenDB
|
|
6
|
+
Author: Uğur Türker Kebeci
|
|
7
|
+
Author-email: Uğur Türker Kebeci <ugurturkerkebeci@users.noreply.github.com>
|
|
8
|
+
Maintainer-email: Uğur Türker Kebeci <ugurturkerkebeci@users.noreply.github.com>
|
|
9
|
+
License: MIT
|
|
10
|
+
Project-URL: Homepage, https://github.com/ugurturkerkebeci/MergenDB
|
|
11
|
+
Project-URL: Repository, https://github.com/ugurturkerkebeci/MergenDB.git
|
|
12
|
+
Project-URL: Bug Tracker, https://github.com/ugurturkerkebeci/MergenDB/issues
|
|
13
|
+
Project-URL: Documentation, https://github.com/ugurturkerkebeci/MergenDB#readme
|
|
14
|
+
Keywords: database,columnar,compression,embedded,edge-computing,query-engine,analytics,sql,mergenql
|
|
15
|
+
Classifier: Development Status :: 4 - Beta
|
|
16
|
+
Classifier: Intended Audience :: Developers
|
|
17
|
+
Classifier: Intended Audience :: Information Technology
|
|
18
|
+
Classifier: License :: OSI Approved :: MIT License
|
|
19
|
+
Classifier: Operating System :: OS Independent
|
|
20
|
+
Classifier: Programming Language :: Python :: 3
|
|
21
|
+
Classifier: Programming Language :: Python :: 3.8
|
|
22
|
+
Classifier: Programming Language :: Python :: 3.9
|
|
23
|
+
Classifier: Programming Language :: Python :: 3.10
|
|
24
|
+
Classifier: Programming Language :: Python :: 3.11
|
|
25
|
+
Classifier: Programming Language :: Python :: 3.12
|
|
26
|
+
Classifier: Topic :: Database
|
|
27
|
+
Classifier: Topic :: Database :: Database Engines/Servers
|
|
28
|
+
Classifier: Topic :: Scientific/Engineering :: Information Analysis
|
|
29
|
+
Requires-Python: >=3.8
|
|
30
|
+
Description-Content-Type: text/markdown
|
|
31
|
+
License-File: LICENSE
|
|
32
|
+
|
|
33
|
+
# 🏹 MergenDB
|
|
34
|
+
|
|
35
|
+
[](https://pypi.org/project/mergendb/)
|
|
36
|
+
[](https://opensource.org/licenses/MIT)
|
|
37
|
+
[](https://www.python.org/downloads/)
|
|
38
|
+
[](https://github.com/ugurturkerkebeci)
|
|
39
|
+
[](#architecture)
|
|
40
|
+
[](#benchmark)
|
|
41
|
+
|
|
42
|
+
> **"Big Data on Small Hardware"**
|
|
43
|
+
> **MergenDB** is an ultra-compact, columnar, embedded database engine and custom query language (**MergenQL**) designed to run analytical workloads on resource-constrained systems (Raspberry Pi, IoT gateways, low-end VPS, and edge devices) with maximum compression and zero memory exhaustion.
|
|
44
|
+
>
|
|
45
|
+
> 👨💻 **Author & Lead Developer:** **Uğur Türker Kebeci** ([@ugurturkerkebeci](https://github.com/ugurturkerkebeci))
|
|
46
|
+
|
|
47
|
+
Named after **Mergen**, the ancient Turkic deity of wisdom, precision, and archery—who never misses his target.
|
|
48
|
+
|
|
49
|
+
---
|
|
50
|
+
|
|
51
|
+
## 📦 Installation
|
|
52
|
+
|
|
53
|
+
Install MergenDB directly from PyPI via `pip`:
|
|
54
|
+
|
|
55
|
+
```bash
|
|
56
|
+
pip install mergendb
|
|
57
|
+
```
|
|
58
|
+
|
|
59
|
+
*(MergenDB has **zero external dependencies** for its core engine—runs on standard Python 3.8+!)*
|
|
60
|
+
|
|
61
|
+
---
|
|
62
|
+
|
|
63
|
+
## ⚡ Core Philosophy & Architecture
|
|
64
|
+
|
|
65
|
+
Traditional databases (SQLite, Postgres, MySQL) store data in a **row-oriented** layout. If a table has 50 columns and you only query `age` and `salary`, row-oriented engines must read all 50 columns from disk, wasting massive I/O bandwidth and memory.
|
|
66
|
+
|
|
67
|
+
**MergenDB** redesigns storage from the silicon up:
|
|
68
|
+
|
|
69
|
+
```mermaid
|
|
70
|
+
flowchart TD
|
|
71
|
+
RawData["Raw Input Records (JSON/Dicts)"] --> Chunker["Chunker (1024 - 4096 row vectors)"]
|
|
72
|
+
Chunker --> ColSlice["Columnar Vertical Partitioning"]
|
|
73
|
+
|
|
74
|
+
subgraph CompressionEngine ["Adaptive Compression Engine"]
|
|
75
|
+
ColSlice --> RLE["Run-Length Encoding (RLE)"]
|
|
76
|
+
ColSlice --> Dict["Dictionary Encoding (Low Cardinality)"]
|
|
77
|
+
ColSlice --> Delta["Delta / Frame-of-Reference (Timestamps & IDs)"]
|
|
78
|
+
ColSlice --> BitPack["Bit-Packing (8 Bools / Byte)"]
|
|
79
|
+
end
|
|
80
|
+
|
|
81
|
+
CompressionEngine --> ZoneMaps["ZoneMap Generator (Min/Max Indices)"]
|
|
82
|
+
ZoneMaps --> Disk[".mgdb Columnar File on Disk"]
|
|
83
|
+
```
|
|
84
|
+
|
|
85
|
+
### 1. 🗜️ Adaptive Donut Compression (Hardware-Level Encodings)
|
|
86
|
+
* **Bit-Packing:** Booleans are packed 8 to a byte (8x space savings). Small integers use minimal bit-widths.
|
|
87
|
+
* **Delta / Frame-of-Reference (FoR):** Monotonically increasing timestamps or IDs store only differences (+1, +4), reducing 8-byte integers to 1 or 2 bytes.
|
|
88
|
+
* **Dictionary Encoding:** Repeated text and category strings are mapped to 1-2 byte integer IDs.
|
|
89
|
+
* **Run-Length Encoding (RLE):** Sequences of identical values are stored as a single `(value, count)` tuple.
|
|
90
|
+
* **Automatic Algorithm Selection:** MergenDB evaluates candidate encodings for each column block and selects the one with the smallest footprint.
|
|
91
|
+
|
|
92
|
+
### 2. 🎯 ZoneMap Indexing & Block Pruning
|
|
93
|
+
Every data block stores lightweight `min` and `max` metadata. During query execution, **blocks that cannot satisfy the query predicates are completely skipped without reading or decompressing bytes from disk**.
|
|
94
|
+
|
|
95
|
+
### 3. ✂️ Column Pruning
|
|
96
|
+
If a table has 40 columns and your query only asks for `temperature` and `room`, MergenDB seeks directly to those column offsets. **The other 38 columns are never read from disk.**
|
|
97
|
+
|
|
98
|
+
### 4. 🌊 Vectorized & Chunked Streaming
|
|
99
|
+
MergenDB processes data in vectorized chunks (e.g. 1024 values at a time). **A 50 GB database can be queried on a 256 MB RAM machine without Out-Of-Memory (OOM) errors.**
|
|
100
|
+
|
|
101
|
+
---
|
|
102
|
+
|
|
103
|
+
## 📊 Benchmark: MergenDB vs JSON vs CSV
|
|
104
|
+
|
|
105
|
+
Tested on **50,000 realistic IoT telemetry records** (`timestamp`, `device_id`, `building`, `room`, `temperature`, `humidity`, `voltage`, `status`, `is_alert`):
|
|
106
|
+
|
|
107
|
+
| Storage Format | Disk Size (KB) | Ratio vs JSON | Space Saved | Scan Time (50k rows) |
|
|
108
|
+
| :--- | :--- | :--- | :--- | :--- |
|
|
109
|
+
| **JSON Lines (`.jsonl`)** | 9,806 KB | 1.00x | 0.0% | ~ 240 ms |
|
|
110
|
+
| **Standard CSV (`.csv`)** | 3,751 KB | 2.61x | 61.7% | ~ 110 ms |
|
|
111
|
+
| **MergenDB (`.mgdb`)** | **599 KB** | **16.36x** | **93.9%** | **36 ms** |
|
|
112
|
+
|
|
113
|
+
> 🚀 **Result:** MergenDB is **16.3x smaller than JSON** and **6.2x smaller than CSV**, while executing analytical queries in **36 milliseconds**!
|
|
114
|
+
|
|
115
|
+
---
|
|
116
|
+
|
|
117
|
+
## 🏹 MergenQL: The Pipeline Query Language
|
|
118
|
+
|
|
119
|
+
MergenDB introduces **MergenQL**, a modern pipeline-oriented query language where data flows logically from left to right:
|
|
120
|
+
|
|
121
|
+
```text
|
|
122
|
+
FROM "telemetry.mgdb"
|
|
123
|
+
| WHERE temperature > 32.0 AND is_alert == true
|
|
124
|
+
| COMPUTE temp_f = (temperature * 1.8) + 32.0
|
|
125
|
+
| AGGREGATE count(*) AS alert_count, avg(temp_f) AS avg_f BY building
|
|
126
|
+
| SORT alert_count DESC
|
|
127
|
+
| LIMIT 10
|
|
128
|
+
```
|
|
129
|
+
|
|
130
|
+
---
|
|
131
|
+
|
|
132
|
+
## 🚀 Quickstart
|
|
133
|
+
|
|
134
|
+
### 1. Installation
|
|
135
|
+
Clone the repository and install in editable mode:
|
|
136
|
+
```bash
|
|
137
|
+
git clone https://github.com/your-username/MergenDB.git
|
|
138
|
+
cd MergenDB
|
|
139
|
+
pip install -e .
|
|
140
|
+
```
|
|
141
|
+
*(MergenDB has **zero external dependencies** for its core engine—runs on standard Python 3.8+!)*
|
|
142
|
+
|
|
143
|
+
### 2. Python API Example
|
|
144
|
+
|
|
145
|
+
```python
|
|
146
|
+
import mergendb
|
|
147
|
+
|
|
148
|
+
# 1. Define schema
|
|
149
|
+
schema = mergendb.Schema([
|
|
150
|
+
mergendb.ColumnDef("id", mergendb.DataType.INT64),
|
|
151
|
+
mergendb.ColumnDef("device_id", mergendb.DataType.STRING),
|
|
152
|
+
mergendb.ColumnDef("temperature", mergendb.DataType.FLOAT64),
|
|
153
|
+
mergendb.ColumnDef("building", mergendb.DataType.STRING),
|
|
154
|
+
mergendb.ColumnDef("is_alert", mergendb.DataType.BOOL)
|
|
155
|
+
])
|
|
156
|
+
|
|
157
|
+
# 2. Create table and insert records
|
|
158
|
+
table = mergendb.create_table("telemetry.mgdb", schema, block_size=1024)
|
|
159
|
+
|
|
160
|
+
table.insert_many([
|
|
161
|
+
{"id": 1, "device_id": "sensor_01", "temperature": 34.5, "building": "HQ", "is_alert": True},
|
|
162
|
+
{"id": 2, "device_id": "sensor_02", "temperature": 21.0, "building": "HQ", "is_alert": False},
|
|
163
|
+
{"id": 3, "device_id": "sensor_03", "temperature": 39.2, "building": "Factory", "is_alert": True},
|
|
164
|
+
])
|
|
165
|
+
|
|
166
|
+
# 3. Query using MergenQL
|
|
167
|
+
result = mergendb.query("""
|
|
168
|
+
FROM "telemetry.mgdb"
|
|
169
|
+
| WHERE is_alert == true
|
|
170
|
+
| COMPUTE temp_f = (temperature * 1.8) + 32.0
|
|
171
|
+
| SELECT device_id, building, temperature, temp_f
|
|
172
|
+
| SORT temperature DESC
|
|
173
|
+
""")
|
|
174
|
+
|
|
175
|
+
print(result.display())
|
|
176
|
+
```
|
|
177
|
+
|
|
178
|
+
Output:
|
|
179
|
+
```text
|
|
180
|
+
+-----------+----------+-------------+--------+
|
|
181
|
+
| device_id | building | temperature | temp_f |
|
|
182
|
+
+-----------+----------+-------------+--------+
|
|
183
|
+
| sensor_03 | Factory | 39.2 | 102.56 |
|
|
184
|
+
| sensor_01 | HQ | 34.5 | 94.1 |
|
|
185
|
+
+-----------+----------+-------------+--------+
|
|
186
|
+
Returned 2 rows in 0.28 ms | Blocks: 1 scanned, 0 skipped (pruned) | Read: 0.14 KB
|
|
187
|
+
```
|
|
188
|
+
|
|
189
|
+
---
|
|
190
|
+
|
|
191
|
+
## 📥 SQL & Data Ingestion (İçe Aktarma)
|
|
192
|
+
|
|
193
|
+
MergenDB, mevcut veritabanlarınızı doğrudan ultra-kompakt `.mgdb` formatına dönüştürebilir:
|
|
194
|
+
|
|
195
|
+
### 1. SQLite Veritabanını İçe Aktarma
|
|
196
|
+
```python
|
|
197
|
+
import mergendb
|
|
198
|
+
|
|
199
|
+
# Tüm tabloyu veya özel bir SQL sorgusunun sonucunu dönüştürün:
|
|
200
|
+
table = mergendb.from_sqlite(
|
|
201
|
+
sqlite_path="legacy.db",
|
|
202
|
+
table_name="orders",
|
|
203
|
+
output_mgdb_path="orders.mgdb"
|
|
204
|
+
)
|
|
205
|
+
```
|
|
206
|
+
|
|
207
|
+
### 2. SQL Dump Dosyasını (`.sql`) İçe Aktarma
|
|
208
|
+
Postgres/MySQL veya standart SQL dump dosyalarını doğrudan aktarın:
|
|
209
|
+
```python
|
|
210
|
+
table = mergendb.from_sql_dump(
|
|
211
|
+
sql_dump_path="backup.sql",
|
|
212
|
+
output_mgdb_path="products.mgdb"
|
|
213
|
+
)
|
|
214
|
+
```
|
|
215
|
+
|
|
216
|
+
### 3. CSV Dosyasını Otomatik Tip Algılama ile Aktarma
|
|
217
|
+
```python
|
|
218
|
+
table = mergendb.from_csv(
|
|
219
|
+
csv_path="dataset.csv",
|
|
220
|
+
output_mgdb_path="dataset.mgdb"
|
|
221
|
+
)
|
|
222
|
+
```
|
|
223
|
+
|
|
224
|
+
### 4. CLI / REPL Üzerinden İçe Aktarma
|
|
225
|
+
```text
|
|
226
|
+
mergen> .import sqlite legacy.db orders orders.mgdb
|
|
227
|
+
mergen> .import sql backup.sql products.mgdb
|
|
228
|
+
mergen> .import csv data.csv data.mgdb
|
|
229
|
+
```
|
|
230
|
+
|
|
231
|
+
---
|
|
232
|
+
|
|
233
|
+
## 💻 Interactive CLI / REPL
|
|
234
|
+
|
|
235
|
+
Launch the interactive MergenDB terminal shell:
|
|
236
|
+
|
|
237
|
+
```bash
|
|
238
|
+
python -m mergendb.cli.repl
|
|
239
|
+
# or if installed:
|
|
240
|
+
mergen
|
|
241
|
+
```
|
|
242
|
+
|
|
243
|
+
```text
|
|
244
|
+
__ __ _____ ____
|
|
245
|
+
| \/ | | __ \| _ \
|
|
246
|
+
| \ / | ___ _ __ __ _ ___ _ __ | | | | |_) |
|
|
247
|
+
| |\/| |/ _ \ '__/ _` |/ _ \ '_ \ | | | | _ <
|
|
248
|
+
| | | | __/ | | (_| | __/ | | | | |__| | |_) |
|
|
249
|
+
|_| |_|\___|_| \__, |\___|_| |_| |_____/|____/
|
|
250
|
+
__/ |
|
|
251
|
+
|___/ v0.1.0 (Edge Columnar Engine)
|
|
252
|
+
|
|
253
|
+
mergen> .info telemetry.mgdb
|
|
254
|
+
--- Storage Footprint: telemetry.mgdb ---
|
|
255
|
+
Total Rows : 50,000
|
|
256
|
+
Total Blocks : 25
|
|
257
|
+
File Size on Disk : 599.40 KB (613,785 bytes)
|
|
258
|
+
Compression Ratio : 16.36x (Saved 93.9% space)
|
|
259
|
+
|
|
260
|
+
mergen> FROM "telemetry.mgdb"
|
|
261
|
+
...> | WHERE temperature > 38.0
|
|
262
|
+
...> | AGGREGATE count(*) AS critical_count BY room
|
|
263
|
+
...> | SORT critical_count DESC;
|
|
264
|
+
```
|
|
265
|
+
|
|
266
|
+
---
|
|
267
|
+
|
|
268
|
+
## 🧪 Testing
|
|
269
|
+
|
|
270
|
+
Run the full automated test suite:
|
|
271
|
+
```bash
|
|
272
|
+
python -m unittest discover tests
|
|
273
|
+
```
|
|
274
|
+
|
|
275
|
+
---
|
|
276
|
+
|
|
277
|
+
## 🗺️ Roadmap
|
|
278
|
+
- [x] Columnar binary storage format (`.mgdb`) with headers and footers
|
|
279
|
+
- [x] Adaptive encodings (Bit-Packing, RLE, Dictionary, Delta/FoR, Raw)
|
|
280
|
+
- [x] ZoneMap min/max block pruning
|
|
281
|
+
- [x] Column projection pruning
|
|
282
|
+
- [x] MergenQL Lexer, Parser, and AST
|
|
283
|
+
- [x] Vectorized execution engine with aggregations and computes
|
|
284
|
+
- [x] Interactive REPL CLI
|
|
285
|
+
- [ ] Memory-mapped (mmap) zero-copy block loader
|
|
286
|
+
- [ ] Multi-threaded block scanner
|
|
287
|
+
- [ ] In-place B-Tree secondary indexing
|
|
288
|
+
- [ ] C extension / Rust bindings for SIMD bit-unpacking
|
|
289
|
+
|
|
290
|
+
---
|
|
291
|
+
|
|
292
|
+
## 📄 License
|
|
293
|
+
MIT License. Created for the open-source community to empower edge computing and low-resource data analytics.
|
mergendb-0.1.0/README.md
ADDED
|
@@ -0,0 +1,261 @@
|
|
|
1
|
+
# 🏹 MergenDB
|
|
2
|
+
|
|
3
|
+
[](https://pypi.org/project/mergendb/)
|
|
4
|
+
[](https://opensource.org/licenses/MIT)
|
|
5
|
+
[](https://www.python.org/downloads/)
|
|
6
|
+
[](https://github.com/ugurturkerkebeci)
|
|
7
|
+
[](#architecture)
|
|
8
|
+
[](#benchmark)
|
|
9
|
+
|
|
10
|
+
> **"Big Data on Small Hardware"**
|
|
11
|
+
> **MergenDB** is an ultra-compact, columnar, embedded database engine and custom query language (**MergenQL**) designed to run analytical workloads on resource-constrained systems (Raspberry Pi, IoT gateways, low-end VPS, and edge devices) with maximum compression and zero memory exhaustion.
|
|
12
|
+
>
|
|
13
|
+
> 👨💻 **Author & Lead Developer:** **Uğur Türker Kebeci** ([@ugurturkerkebeci](https://github.com/ugurturkerkebeci))
|
|
14
|
+
|
|
15
|
+
Named after **Mergen**, the ancient Turkic deity of wisdom, precision, and archery—who never misses his target.
|
|
16
|
+
|
|
17
|
+
---
|
|
18
|
+
|
|
19
|
+
## 📦 Installation
|
|
20
|
+
|
|
21
|
+
Install MergenDB directly from PyPI via `pip`:
|
|
22
|
+
|
|
23
|
+
```bash
|
|
24
|
+
pip install mergendb
|
|
25
|
+
```
|
|
26
|
+
|
|
27
|
+
*(MergenDB has **zero external dependencies** for its core engine—runs on standard Python 3.8+!)*
|
|
28
|
+
|
|
29
|
+
---
|
|
30
|
+
|
|
31
|
+
## ⚡ Core Philosophy & Architecture
|
|
32
|
+
|
|
33
|
+
Traditional databases (SQLite, Postgres, MySQL) store data in a **row-oriented** layout. If a table has 50 columns and you only query `age` and `salary`, row-oriented engines must read all 50 columns from disk, wasting massive I/O bandwidth and memory.
|
|
34
|
+
|
|
35
|
+
**MergenDB** redesigns storage from the silicon up:
|
|
36
|
+
|
|
37
|
+
```mermaid
|
|
38
|
+
flowchart TD
|
|
39
|
+
RawData["Raw Input Records (JSON/Dicts)"] --> Chunker["Chunker (1024 - 4096 row vectors)"]
|
|
40
|
+
Chunker --> ColSlice["Columnar Vertical Partitioning"]
|
|
41
|
+
|
|
42
|
+
subgraph CompressionEngine ["Adaptive Compression Engine"]
|
|
43
|
+
ColSlice --> RLE["Run-Length Encoding (RLE)"]
|
|
44
|
+
ColSlice --> Dict["Dictionary Encoding (Low Cardinality)"]
|
|
45
|
+
ColSlice --> Delta["Delta / Frame-of-Reference (Timestamps & IDs)"]
|
|
46
|
+
ColSlice --> BitPack["Bit-Packing (8 Bools / Byte)"]
|
|
47
|
+
end
|
|
48
|
+
|
|
49
|
+
CompressionEngine --> ZoneMaps["ZoneMap Generator (Min/Max Indices)"]
|
|
50
|
+
ZoneMaps --> Disk[".mgdb Columnar File on Disk"]
|
|
51
|
+
```
|
|
52
|
+
|
|
53
|
+
### 1. 🗜️ Adaptive Donut Compression (Hardware-Level Encodings)
|
|
54
|
+
* **Bit-Packing:** Booleans are packed 8 to a byte (8x space savings). Small integers use minimal bit-widths.
|
|
55
|
+
* **Delta / Frame-of-Reference (FoR):** Monotonically increasing timestamps or IDs store only differences (+1, +4), reducing 8-byte integers to 1 or 2 bytes.
|
|
56
|
+
* **Dictionary Encoding:** Repeated text and category strings are mapped to 1-2 byte integer IDs.
|
|
57
|
+
* **Run-Length Encoding (RLE):** Sequences of identical values are stored as a single `(value, count)` tuple.
|
|
58
|
+
* **Automatic Algorithm Selection:** MergenDB evaluates candidate encodings for each column block and selects the one with the smallest footprint.
|
|
59
|
+
|
|
60
|
+
### 2. 🎯 ZoneMap Indexing & Block Pruning
|
|
61
|
+
Every data block stores lightweight `min` and `max` metadata. During query execution, **blocks that cannot satisfy the query predicates are completely skipped without reading or decompressing bytes from disk**.
|
|
62
|
+
|
|
63
|
+
### 3. ✂️ Column Pruning
|
|
64
|
+
If a table has 40 columns and your query only asks for `temperature` and `room`, MergenDB seeks directly to those column offsets. **The other 38 columns are never read from disk.**
|
|
65
|
+
|
|
66
|
+
### 4. 🌊 Vectorized & Chunked Streaming
|
|
67
|
+
MergenDB processes data in vectorized chunks (e.g. 1024 values at a time). **A 50 GB database can be queried on a 256 MB RAM machine without Out-Of-Memory (OOM) errors.**
|
|
68
|
+
|
|
69
|
+
---
|
|
70
|
+
|
|
71
|
+
## 📊 Benchmark: MergenDB vs JSON vs CSV
|
|
72
|
+
|
|
73
|
+
Tested on **50,000 realistic IoT telemetry records** (`timestamp`, `device_id`, `building`, `room`, `temperature`, `humidity`, `voltage`, `status`, `is_alert`):
|
|
74
|
+
|
|
75
|
+
| Storage Format | Disk Size (KB) | Ratio vs JSON | Space Saved | Scan Time (50k rows) |
|
|
76
|
+
| :--- | :--- | :--- | :--- | :--- |
|
|
77
|
+
| **JSON Lines (`.jsonl`)** | 9,806 KB | 1.00x | 0.0% | ~ 240 ms |
|
|
78
|
+
| **Standard CSV (`.csv`)** | 3,751 KB | 2.61x | 61.7% | ~ 110 ms |
|
|
79
|
+
| **MergenDB (`.mgdb`)** | **599 KB** | **16.36x** | **93.9%** | **36 ms** |
|
|
80
|
+
|
|
81
|
+
> 🚀 **Result:** MergenDB is **16.3x smaller than JSON** and **6.2x smaller than CSV**, while executing analytical queries in **36 milliseconds**!
|
|
82
|
+
|
|
83
|
+
---
|
|
84
|
+
|
|
85
|
+
## 🏹 MergenQL: The Pipeline Query Language
|
|
86
|
+
|
|
87
|
+
MergenDB introduces **MergenQL**, a modern pipeline-oriented query language where data flows logically from left to right:
|
|
88
|
+
|
|
89
|
+
```text
|
|
90
|
+
FROM "telemetry.mgdb"
|
|
91
|
+
| WHERE temperature > 32.0 AND is_alert == true
|
|
92
|
+
| COMPUTE temp_f = (temperature * 1.8) + 32.0
|
|
93
|
+
| AGGREGATE count(*) AS alert_count, avg(temp_f) AS avg_f BY building
|
|
94
|
+
| SORT alert_count DESC
|
|
95
|
+
| LIMIT 10
|
|
96
|
+
```
|
|
97
|
+
|
|
98
|
+
---
|
|
99
|
+
|
|
100
|
+
## 🚀 Quickstart
|
|
101
|
+
|
|
102
|
+
### 1. Installation
|
|
103
|
+
Clone the repository and install in editable mode:
|
|
104
|
+
```bash
|
|
105
|
+
git clone https://github.com/your-username/MergenDB.git
|
|
106
|
+
cd MergenDB
|
|
107
|
+
pip install -e .
|
|
108
|
+
```
|
|
109
|
+
*(MergenDB has **zero external dependencies** for its core engine—runs on standard Python 3.8+!)*
|
|
110
|
+
|
|
111
|
+
### 2. Python API Example
|
|
112
|
+
|
|
113
|
+
```python
|
|
114
|
+
import mergendb
|
|
115
|
+
|
|
116
|
+
# 1. Define schema
|
|
117
|
+
schema = mergendb.Schema([
|
|
118
|
+
mergendb.ColumnDef("id", mergendb.DataType.INT64),
|
|
119
|
+
mergendb.ColumnDef("device_id", mergendb.DataType.STRING),
|
|
120
|
+
mergendb.ColumnDef("temperature", mergendb.DataType.FLOAT64),
|
|
121
|
+
mergendb.ColumnDef("building", mergendb.DataType.STRING),
|
|
122
|
+
mergendb.ColumnDef("is_alert", mergendb.DataType.BOOL)
|
|
123
|
+
])
|
|
124
|
+
|
|
125
|
+
# 2. Create table and insert records
|
|
126
|
+
table = mergendb.create_table("telemetry.mgdb", schema, block_size=1024)
|
|
127
|
+
|
|
128
|
+
table.insert_many([
|
|
129
|
+
{"id": 1, "device_id": "sensor_01", "temperature": 34.5, "building": "HQ", "is_alert": True},
|
|
130
|
+
{"id": 2, "device_id": "sensor_02", "temperature": 21.0, "building": "HQ", "is_alert": False},
|
|
131
|
+
{"id": 3, "device_id": "sensor_03", "temperature": 39.2, "building": "Factory", "is_alert": True},
|
|
132
|
+
])
|
|
133
|
+
|
|
134
|
+
# 3. Query using MergenQL
|
|
135
|
+
result = mergendb.query("""
|
|
136
|
+
FROM "telemetry.mgdb"
|
|
137
|
+
| WHERE is_alert == true
|
|
138
|
+
| COMPUTE temp_f = (temperature * 1.8) + 32.0
|
|
139
|
+
| SELECT device_id, building, temperature, temp_f
|
|
140
|
+
| SORT temperature DESC
|
|
141
|
+
""")
|
|
142
|
+
|
|
143
|
+
print(result.display())
|
|
144
|
+
```
|
|
145
|
+
|
|
146
|
+
Output:
|
|
147
|
+
```text
|
|
148
|
+
+-----------+----------+-------------+--------+
|
|
149
|
+
| device_id | building | temperature | temp_f |
|
|
150
|
+
+-----------+----------+-------------+--------+
|
|
151
|
+
| sensor_03 | Factory | 39.2 | 102.56 |
|
|
152
|
+
| sensor_01 | HQ | 34.5 | 94.1 |
|
|
153
|
+
+-----------+----------+-------------+--------+
|
|
154
|
+
Returned 2 rows in 0.28 ms | Blocks: 1 scanned, 0 skipped (pruned) | Read: 0.14 KB
|
|
155
|
+
```
|
|
156
|
+
|
|
157
|
+
---
|
|
158
|
+
|
|
159
|
+
## 📥 SQL & Data Ingestion (İçe Aktarma)
|
|
160
|
+
|
|
161
|
+
MergenDB, mevcut veritabanlarınızı doğrudan ultra-kompakt `.mgdb` formatına dönüştürebilir:
|
|
162
|
+
|
|
163
|
+
### 1. SQLite Veritabanını İçe Aktarma
|
|
164
|
+
```python
|
|
165
|
+
import mergendb
|
|
166
|
+
|
|
167
|
+
# Tüm tabloyu veya özel bir SQL sorgusunun sonucunu dönüştürün:
|
|
168
|
+
table = mergendb.from_sqlite(
|
|
169
|
+
sqlite_path="legacy.db",
|
|
170
|
+
table_name="orders",
|
|
171
|
+
output_mgdb_path="orders.mgdb"
|
|
172
|
+
)
|
|
173
|
+
```
|
|
174
|
+
|
|
175
|
+
### 2. SQL Dump Dosyasını (`.sql`) İçe Aktarma
|
|
176
|
+
Postgres/MySQL veya standart SQL dump dosyalarını doğrudan aktarın:
|
|
177
|
+
```python
|
|
178
|
+
table = mergendb.from_sql_dump(
|
|
179
|
+
sql_dump_path="backup.sql",
|
|
180
|
+
output_mgdb_path="products.mgdb"
|
|
181
|
+
)
|
|
182
|
+
```
|
|
183
|
+
|
|
184
|
+
### 3. CSV Dosyasını Otomatik Tip Algılama ile Aktarma
|
|
185
|
+
```python
|
|
186
|
+
table = mergendb.from_csv(
|
|
187
|
+
csv_path="dataset.csv",
|
|
188
|
+
output_mgdb_path="dataset.mgdb"
|
|
189
|
+
)
|
|
190
|
+
```
|
|
191
|
+
|
|
192
|
+
### 4. CLI / REPL Üzerinden İçe Aktarma
|
|
193
|
+
```text
|
|
194
|
+
mergen> .import sqlite legacy.db orders orders.mgdb
|
|
195
|
+
mergen> .import sql backup.sql products.mgdb
|
|
196
|
+
mergen> .import csv data.csv data.mgdb
|
|
197
|
+
```
|
|
198
|
+
|
|
199
|
+
---
|
|
200
|
+
|
|
201
|
+
## 💻 Interactive CLI / REPL
|
|
202
|
+
|
|
203
|
+
Launch the interactive MergenDB terminal shell:
|
|
204
|
+
|
|
205
|
+
```bash
|
|
206
|
+
python -m mergendb.cli.repl
|
|
207
|
+
# or if installed:
|
|
208
|
+
mergen
|
|
209
|
+
```
|
|
210
|
+
|
|
211
|
+
```text
|
|
212
|
+
__ __ _____ ____
|
|
213
|
+
| \/ | | __ \| _ \
|
|
214
|
+
| \ / | ___ _ __ __ _ ___ _ __ | | | | |_) |
|
|
215
|
+
| |\/| |/ _ \ '__/ _` |/ _ \ '_ \ | | | | _ <
|
|
216
|
+
| | | | __/ | | (_| | __/ | | | | |__| | |_) |
|
|
217
|
+
|_| |_|\___|_| \__, |\___|_| |_| |_____/|____/
|
|
218
|
+
__/ |
|
|
219
|
+
|___/ v0.1.0 (Edge Columnar Engine)
|
|
220
|
+
|
|
221
|
+
mergen> .info telemetry.mgdb
|
|
222
|
+
--- Storage Footprint: telemetry.mgdb ---
|
|
223
|
+
Total Rows : 50,000
|
|
224
|
+
Total Blocks : 25
|
|
225
|
+
File Size on Disk : 599.40 KB (613,785 bytes)
|
|
226
|
+
Compression Ratio : 16.36x (Saved 93.9% space)
|
|
227
|
+
|
|
228
|
+
mergen> FROM "telemetry.mgdb"
|
|
229
|
+
...> | WHERE temperature > 38.0
|
|
230
|
+
...> | AGGREGATE count(*) AS critical_count BY room
|
|
231
|
+
...> | SORT critical_count DESC;
|
|
232
|
+
```
|
|
233
|
+
|
|
234
|
+
---
|
|
235
|
+
|
|
236
|
+
## 🧪 Testing
|
|
237
|
+
|
|
238
|
+
Run the full automated test suite:
|
|
239
|
+
```bash
|
|
240
|
+
python -m unittest discover tests
|
|
241
|
+
```
|
|
242
|
+
|
|
243
|
+
---
|
|
244
|
+
|
|
245
|
+
## 🗺️ Roadmap
|
|
246
|
+
- [x] Columnar binary storage format (`.mgdb`) with headers and footers
|
|
247
|
+
- [x] Adaptive encodings (Bit-Packing, RLE, Dictionary, Delta/FoR, Raw)
|
|
248
|
+
- [x] ZoneMap min/max block pruning
|
|
249
|
+
- [x] Column projection pruning
|
|
250
|
+
- [x] MergenQL Lexer, Parser, and AST
|
|
251
|
+
- [x] Vectorized execution engine with aggregations and computes
|
|
252
|
+
- [x] Interactive REPL CLI
|
|
253
|
+
- [ ] Memory-mapped (mmap) zero-copy block loader
|
|
254
|
+
- [ ] Multi-threaded block scanner
|
|
255
|
+
- [ ] In-place B-Tree secondary indexing
|
|
256
|
+
- [ ] C extension / Rust bindings for SIMD bit-unpacking
|
|
257
|
+
|
|
258
|
+
---
|
|
259
|
+
|
|
260
|
+
## 📄 License
|
|
261
|
+
MIT License. Created for the open-source community to empower edge computing and low-resource data analytics.
|
|
@@ -0,0 +1,28 @@
|
|
|
1
|
+
"""
|
|
2
|
+
MergenDB: Ultra-compact, columnar embedded database engine for edge and resource-constrained environments.
|
|
3
|
+
"""
|
|
4
|
+
|
|
5
|
+
from mergendb.client import (
|
|
6
|
+
MergenDB, Table, query, create_table, open_table,
|
|
7
|
+
from_sqlite, from_sql_dump, from_csv
|
|
8
|
+
)
|
|
9
|
+
from mergendb.core.schema import Schema, ColumnDef
|
|
10
|
+
from mergendb.core.types import DataType
|
|
11
|
+
from mergendb.query.engine import QueryResult
|
|
12
|
+
|
|
13
|
+
__version__ = "0.1.0"
|
|
14
|
+
__author__ = "Uğur Türker Kebeci (ugurturkerkebeci)"
|
|
15
|
+
__all__ = [
|
|
16
|
+
"MergenDB",
|
|
17
|
+
"Table",
|
|
18
|
+
"query",
|
|
19
|
+
"create_table",
|
|
20
|
+
"open_table",
|
|
21
|
+
"from_sqlite",
|
|
22
|
+
"from_sql_dump",
|
|
23
|
+
"from_csv",
|
|
24
|
+
"Schema",
|
|
25
|
+
"ColumnDef",
|
|
26
|
+
"DataType",
|
|
27
|
+
"QueryResult"
|
|
28
|
+
]
|