datalevin/datalevin
datalevin/datalevin has 1,495 GitHub stars and 91 forks. GitHot measured +1 stars in 24 hours and +3 in 7 days. Last checked 2026-11-10 03:33 UTC. Last push 2026-11-02.
A simple, fast and versatile Datalog database
实测星标增长
- 24小时
- +1
- 7天
- +3
- 15天
- 更新延迟
- 1个月
- 更新延迟
各周期内的星标净变化,周期相互重叠,并非每日新增。缺失的测量保持空白。星标代表关注度,不代表软件质量。
README.md
原文
Datalevin
🧘 Simple, fast and versatile Datalog database for everyone 💽
I love Datalog, why hasn't everyone used this already?
Datalevin (/ˈdadə ˈlevən/, "levin" means "lightning") is a simple durable Datalog database. Here's what a Datalog query looks like in Datalevin:
(d/q '[:find ?name ?total
:in $ ?year
:where [?sales :sales/year ?year]
[?sales :sales/total ?total]
[?sales :sales/customer ?customer]
[?customer :customers/name ?name]]
(d/db conn) 2026)
:question: Why
The rationale is to have a simple, fast, versatile and open source Datalog query engine running on durable storage. An extensive discussion of the rationale is at https://datalevin.org/
It is our observation that many developers prefer the flavor of Datalog popularized by Datomic® over any flavor of SQL, once they get to use it. Perhaps it is because Datalog is more declarative and composable than SQL, e.g. the automatic implicit joins seem to be its killer feature. In addition, the recursive rules feature of Datalog makes it suitable for graph queries and deductive reasoning.
The feature set of Datomic® may not be a good fit for some use cases. One thing that may confuse some users is its temporal features. To keep things simple and familiar, Datalevin behaves the same way as most other databases: when data are deleted, they are gone. Datalevin also follows the widely accepted principles of ACID, instead of introducing unusual semantics.
In addition to support Datomic® flavor of Datalog query language, Datalevin has a novel cost-based query optimizer with a much better query performance, which is competitive with SQL RDBMS such as PostgreSQL and SQLite and graph databases such as Neo4j.
Datalevin provides robust ACID transaction features on the basis of our fork of LMDB, known for its high read performance. With built-in support for WAL and asynchronous transaction, Datalevin can also handle write intensive workload.
Datalevin can store large document (< 2 GiB) and automatically build index by paths for JSON, EDN and Markdown documents, so it can be used as a document database, similar to MongoDB or PostgreSQL JSONB column.
Datalevin supports vector database features by integrating an efficient SIMD accelerated vector indexing and search library. Datalevin has a novel full-text search engine that has competitive search performance.
Datalevin is also AI-native. It ships with a built-in local MCP server. Datalevin supports in-DB embedding and text generation with built-in llama.cpp.
Datalevin can be used as a fast key-value store for EDN data. The native EDN data capability of Datalevin should be beneficial for Clojure programs.
Datalevin can be used as a library, embedded in applications to manage state, e.g. used like SQLite; or it can run in a networked client/server mode (default port is 8898) with a Raft consensus based high availability cluster configuration with full-fledged role-based access control (RBAC); or it can be used as a babashka pod for shell scripting.
For embedded usage, Java, Python, Node.js and Clojure are currently supported.
More information about our vision and design decisions can be found in these resources in chronicle order:
- Post Datalevin 1.1.0: State-of-the-Art Performance Across Data Models
- Interview Clojure Corner Interview with Huahai Yang
- Book Datalevin: the Definite Guide to Logical and Intelligent Databases
- Post Triple Store, Triple Progress: Datalevin Posited for the Future
- Post Achieving High Throughput and Low Latency through Adaptive Asynchronous Transaction
- Post Competing for the JOB with a Triplestore
- Post If I had to Pick One: Datalevin
- Post T-Wand: Beat Lucene in Less Than 600 Lines of Code
- Presentation 2020 London Clojurians Meetup
:truck: Installation
Datalevin is simple to add as a dependency to your project written in Java, Python, node.js or Clojure. There are also several other installation options. Please see details in Installation Documentation
:green_book: Documentation
The searchable online user guide accepts user-submitted examples so practical usage patterns can be shared with the community.
The complete book is available in print and ebook formats. It includes five additional chapters on AI memory that are not part of the online guide.
Please refer to the Clojure API documentation and JavaDoc for API details.
For source integration development, see the federation adapter guide, covering the current embedded query-source SPI, mapping examples, and adapter validation.
:tada: Quick Examples
Datalevin is aimed to be a versatile database.
Use as a Datalog store
Here is a simple Clojure code example using Datalevin:
(require '[datalevin.core :as d])
;; Define an optional schema.
;; Note that pre-defined schema is optional, as Datalevin does schema-on-write.
;; However, attributes requiring special handling need to be defined in schema,
;; e.g. range query, many cardinality, uniqueness, reference type, etc.
;; Similar to Datascript, Datalevin schemas differ from Datomic®:
;; - The schema must be a map of maps, not a vector of maps.
;; - It is not `transact`ed into the db but passed when acquiring connections.
;; - Use `update-schema` to update the schema of an open connection to a DB.
(def schema {:aka {:db/cardinality :db.cardinality/many}
;; :db/valueType is optional, if unspecified, the attribute will be
;; treated as EDN blobs, and may not be optimal for range queries
:name {:db/valueType :db.type/string
:db/unique :db.unique/identity}})
;; Create DB on disk and connect to it, assume write permission to create the dir
(def conn (d/get-conn "/tmp/datalevin/mydb" schema))
;; or if you have a Datalevin server running on myhost with default port 8898
;; (def conn (d/get-conn "dtlv://myname:mypasswd@myhost/mydb" schema))
;; Schema input patches existing attribute definitions: omitted properties are
;; preserved. Use :db/retract as a property value to remove that property.
;; Internal :db/aid values returned by d/schema are ignored in schema input.
;; Property patches, value migrations, deletions, and renames commit atomically;
;; repeating a completed deletion or rename is safe.
;; (d/update-schema conn {:name {:db/unique :db/retract}})
;; New idoc and vec attributes default to :db/noindex true, unless unique or
;; explicitly declared with :db/noindex false. Existing attributes keep their
;; indexing policy. Other types participate in AVE by default. For values read
;; only through entity access or pull, declare :db/noindex true to omit AVE:
;; (d/update-schema conn {:document/body {:db/valueType :db.type/string
;; :db/noindex true}})
;; Query conditions on that attribute throw an error. To enable them later,
;; atomically backfill AVE and remove :db/noindex, including on a remote DB:
;; (d/index-attr conn :document/body)
;; Unique and reference attributes cannot opt out. Directly changing
;; :db/noindex on a populated attribute is rejected; use index-attr to enable it.
;; Transact some data
;; `:nation` is not defined in schema, so it will be treated as an EDN blob
(d/transact! conn
[{:name "Frege", :db/id -1, :nation "France", :aka ["foo" "fred"]}
{:name "Peirce", :db/id -2, :nation "france"}
{:name "De Morgan", :db/id -3, :nation "English"}])
;; Query the data
(d/q '[:find ?nation
:in $ ?alias
:where
[?e :aka ?alias]
[?e :nation ?nation]]
(d/db conn)
"fred")
;; => #{["France"]}
;; Retract the name attribute of an entity
(d/transact! conn [[:db/retract 1 :name "Frege"]])
;; Pull the entity, now the name is gone
(d/q '[:find (pull ?e [*])
:in $ ?alias
:where
[?e :aka ?alias]]
(d/db conn)
"fred")
;; => ([{:db/id 1, :aka ["foo" "fred"], :nation "France"}])
;; Close DB connection
(d/close conn)
Use as a key-value store
Datalevin packages the underlying LMDB database as a convenient key-value store for EDN data.
(require '[datalevin.core :as d])
(import '[java.util Date])
;; Open a key value DB on disk and get the DB handle
(def db (d/open-kv "/tmp/datalevin/mykvdb"))
;; or if you have a Datalevin server running on myhost with default port 8898
;; (def db (d/open-kv "dtlv://myname:mypasswd@myhost/mykvdb" schema))
;; Define some table (called "dbi", or sub-databases in LMDB) names
(def misc-table "misc-test-table")
(def date-table "date-test-table")
;; Open the tables
(d/open-dbi db misc-table)
(d/open-dbi db date-table)
;; Transact some data, a transaction can put data into multiple tables
;; Optionally, data type can be specified to help with range query
(d/transact-kv
db
[[:put misc-table :datalevin "Hello, world!"]
[:put misc-table 42 {:saying "So Long, and thanks for all the fish"
:source "The Hitchhiker's Guide to the Galaxy"}]
[:put date-table #inst "1991-12-25" "USSR broke apart" :instant]
[:put date-table #inst "1989-11-09" "The fall of the Berlin Wall" :instant]])
;; Get the value with the key
(d/get-value db misc-table :datalevin)
;; => "Hello, world!"
(d/get-value db misc-table 42)
;; => {:saying "So Long, and thanks for all the fish",
;; :source "The Hitchhiker's Guide to the Galaxy"}
;; Range query, from unix epoch time to now
(d/get-range db date-table [:closed (Date. 0) (Date.)] :instant)
;; => [[#inst "1989-11-09T00:00:00.000-00:00" "The fall of the Berlin Wall"]
;; [#inst "1991-12-25T00:00:00.000-00:00" "USSR broke apart"]]
;; This returns a PersistentVector - e.g. reads all data in JVM memory
(d/get-range db misc-table [:all])
;; => [[42 {:saying "So Long, and thanks for all the fish",
;; :source "The Hitchhiker's Guide to the Galaxy"}]
;; [:datalevin "Hello, world!"]]
;; This allows you to iterate over all DB keys inside a transaction.
;; You can perform writes inside the transaction.
;; Avoid long-lived transactions. Read transactions prevent reuse of pages freed
;; by newer write transactions, thus the database can grow quickly.
;; Write transactions prevent other write transactions, since writes are serialized.
(d/visit db misc-table
(fn [kv]
(let [k (d/read-buffer (d/k kv) :data)]
(when (= k 42)
(d/transact-kv db [[:put misc-table 42 "Don't panic"]]))))
[:all])
(d/get-range db misc-table [:all])
;; => [[42 "Don't panic"] [:datalevin "Hello, world!"]]
;; Delete some data
(d/transact-kv db [[:del misc-table 42]])
;; Now it's gone
(d/get-value db misc-table 42)
;; => nil
;; Close key value db
(d/close-kv db)
:bar_chart: Benchmarks
This repository contains several benchmarks that compare performance of Datalevin with other systems.
The snapshots summarized below were conducted on a 2023 MacBook Pro, Apple M3 Pro chip with 12 cores, 36 GB memory and 1TB SSD drive.
Write
The write benchmark compares Datalevin Datalog transactions with SQLite under explicitly verified durability settings.
In pure write, the one-million-person-record matrix covers batches 1, 10, 100, and 1000. Datalevin led at default sync mode in batches 1 and 1000, and default WAL mode in batches 10, 100 and 1000; SQLite led the other rows. Datalevin's async write modes are much faster, as expected.
For concurrent writes in default WAL mode, Datalevin led in all batches in both 2 and 4 concurrent threads.
For 50/50 mixed read/write, Datalevin held slight lead.
Read
Datalevin supports multiple database paradigms.
Relational
We compared Datalevin with PostgreSQL and SQLite in handling complex relational queries, using Join Order Benchmark. The chart below plots query latency for all 113 queries in the benchmark.
In the current second-pass snapshot, Datalevin completed the 113 queries in 38.1 seconds. PostgreSQL's retained 128.2-second total is 3.37X Datalevin's, while SQLite's 281.8-second completed-query subtotal is 7.40X Datalevin's, with another nine queries reaching the one-minute timeout. The gain is mainly due to shorter query execution time as Datalevin's query optimizer generates better plans.
Graph
We compare Datalevin with Neo4j Community Embedded using the 21 read queries in the LDBC SNB benchmark, an unofficial, single-execution local scale factor 1 snapshot. Datalevin's summed measured query time was 3.890 seconds versus 27.406 seconds for Neo4j. Neo4j's sum was 7.046X Datalevin's, the equal-query Neo4j/Datalevin geometric-mean ratio was 4.996X, and Datalevin had the lower time on 20 of 21 queries.
Document
The idoc benchmark compares Datalevin's indexed documents with PostgreSQL JSONB, SQLite JSON1, and MongoDB BSON. It combines YCSB-style reads and writes with nested equality, range, wildcard-path, and array-match queries.
At one caller, Datalevin had the highest throughput in all three workloads. Workload A mixes reads and updates, C is read-only, and F uses read-modify-write.
| Workload | Datalevin | PostgreSQL | SQLite | MongoDB |
|---|---|---|---|---|
| A | 3,358/s | 2,270/s | 438/s | 309/s |
| C | 11,454/s | 2,039/s | 437/s | 2,868/s |
| F | 2,680/s | 1,789/s | 416/s | 192/s |
Logic
Datalevin's rule engine is evaluated with a portable OpenRuleBench-derived suite. It covers recursive transitive closure (TC), nonlinear recursive same-generation fixed points (SG), and nonrecursive Join1 rule DAGs. The benchmark compares Datalevin with 6 alternative systems.
In the current representative comparison, Datalevin had the lowest latency in
all ten selected cells. FF means both query arguments are free, BF fixes the
first argument, and FB fixes the second. The last column divides the fastest
alternative's latency by Datalevin's latency.
| Task | Result rows | Datalevin (ms) | Fastest alternative (ms) | Alternative / Datalevin |
|---|---|---|---|---|
| TC 50K cyclic FF | 1,000,000 | 67.88 | Soufflé 1,030.36 | 15.18X |
| TC 50K acyclic FF | 473,807 | 45.20 | Soufflé 371.93 | 8.23X |
| TC 50K cyclic BF | 1,000 | 4.71 | SQLite 7.04 | 1.49X |
| SG 6K cyclic FF | 869,923 | 70.23 | Soufflé 865.82 | 12.33X |
| SG 6K acyclic FF | 215,263 | 18.91 | Soufflé 89.43 | 4.73X |
| SG 6K acyclic BF | 533 | 6.09 | PostgreSQL 7.28 | 1.20X |
| SG 6K acyclic FB | 541 | 4.66 | PostgreSQL 6.81 | 1.46X |
| Join1 50K b1 FF | 1,000,000 | 86.65 | XSB 1,795.00 | 20.72X |
| Join1 50K b2 FF | 917,680 | 124.85 | XSB 174.00 | 1.39X |
| Join1 50K a BF | 1,000 | 12.01 | XSB 120.00 | 9.99X |
:rocket: Status
Datalevin is extensively tested with property-based testing. It is used in production at Juji (acquired by Accenture), Roam Research, Toka, among many other companies.
If your project is using Datalevin in production, drop a comment in this issue.
:earth_americas: Roadmap
The goal of Datalevin is to simplify data storage and access. We aim to support diverse workloads and use cases.
- 1.3.0 Direct analytics and federation
- 1.4.0 Derived-fact views, rule-head aggregation, and incremental maintenance
- 2.0.0 Compression and KV TTL
- 2.1.0 Entity-level security
- 2.2.0 Provenance annotations
- 3.0.0 Local sharding
- 3.1.0 Distributed data
Completed milestones:
- 0.4.0 Native image and native command line tool. [Done 2021/02/27]
- 0.5.0 Networked server mode with role based access control. [Done 2021/09/06]
- 0.6.0 As a search engine: full-text search across database. [Done 2022/03/10]
- 0.7.0 Explicit transactions, lazy results loading, and results spill to disk when memory is low. [Done 2022/12/15]
- 0.8.0 Long ids; composite tuples; enhanced search engine ingestion speed. [Done 2023/01/19]
- 0.9.0 New Datalog query engine with improved performance. [Done 2024/03/09]
- 0.10.0 Async transaction; boolean search expression and phrase search; as a vector database; counted and prefix compressed KV storage; auto upgrade migration; new rule engine.[Done 2026/01/22]
- 1.0.0 As a document database with automatic path indexing; WAL mode; transaction log access API; read-only replicas; high availability; JSON API; library for Java, Python, and JavaScript; Book.[Done 2026/07/20]
- 1.1.0 AVE storage optimization; transaction and query performance enhancement. [Done 2026/09/02]
- 1.2.0 extensible storage/query for arbitrary data. [Done 2026/10/13]
:arrows_clockwise: Contact
Datalevin will remain open source for the foreseeable future. We appreciate and welcome your contributions or suggestions. Please feel free to file issues or pull requests.
You can join the discussions in the #datalevin channel on Clojurians
Slack or use the Github Discussions feature above.
If commercial support is needed, reach out to https://agenwiz.com
License
Copyright © 2020-2026 Huahai Yang and contributors.
Licensed under Eclipse Public License (see LICENSE).
探索相关项目
Asabeneh/30-Days-Of-Python
30 Days of Python 编程挑战是一份循序渐进的指南,用于在 30 天内学习 Python 编程语言。这项挑战可能需要超过 100 天。请按自己的节奏进行。这些视频或许也有帮助:https://www.youtube.com/channel/UC7PNRuno1rzYPb1xLa4yktw
78,486 星标grafana/grafana
开放且可组合的可观测性与数据可视化平台。可对来自 Prometheus、Loki、Elasticsearch、InfluxDB、Postgres 等众多数据源的指标、日志和追踪进行可视化。
77,790 星标redis/redis
对于正在构建实时数据驱动应用的开发者而言,Redis 是首选、速度最快且功能最丰富的缓存、数据结构服务器和文档与向量查询引擎。
77,332 星标apache/superset
Apache Superset 是一个数据可视化与数据探索平台
75,455 星标