{"id":22730962,"url":"https://github.com/cojen/tupldb","last_synced_at":"2025-12-18T00:03:23.366Z","repository":{"id":5842471,"uuid":"7058672","full_name":"cojen/TuplDB","owner":"cojen","description":"TuplDB is a high-performance, concurrent, transactional, scalable, low-level embedded database.","archived":false,"fork":false,"pushed_at":"2025-03-04T15:40:26.000Z","size":31917,"stargazers_count":119,"open_issues_count":4,"forks_count":23,"subscribers_count":19,"default_branch":"master","last_synced_at":"2025-03-29T04:09:02.771Z","etag":null,"topics":["acid","btree","concurrency","cursor","database","durable","embedded-database","java","key-value-store","nosql","persistence","raft","replication","sorting","storage-engine","transaction","transactional","transactions"],"latest_commit_sha":null,"homepage":"","language":"Java","has_issues":true,"has_wiki":null,"has_pages":null,"mirror_url":null,"source_name":null,"license":"agpl-3.0","status":null,"scm":"git","pull_requests_enabled":true,"icon_url":"https://github.com/cojen.png","metadata":{"files":{"readme":"README.md","changelog":"CHANGELOG.md","contributing":null,"funding":null,"license":"LICENSE.txt","code_of_conduct":null,"threat_model":null,"audit":null,"citation":null,"codeowners":null,"security":null,"support":null,"governance":null,"roadmap":null,"authors":null,"dei":null,"publiccode":null,"codemeta":null}},"created_at":"2012-12-07T19:30:36.000Z","updated_at":"2025-03-27T17:57:16.000Z","dependencies_parsed_at":"2024-03-03T19:31:33.679Z","dependency_job_id":"891b5ad5-4faf-4077-9c22-e3ad379a7923","html_url":"https://github.com/cojen/TuplDB","commit_stats":null,"previous_names":["cojen/tupl"],"tags_count":72,"template":false,"template_full_name":null,"repository_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/cojen%2FTuplDB","tags_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/cojen%2FTuplDB/tags","releases_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/cojen%2FTuplDB/releases","manifests_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/cojen%2FTuplDB/manifests","owner_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/owners/cojen","download_url":"https://codeload.github.com/cojen/TuplDB/tar.gz/refs/heads/master","host":{"name":"GitHub","url":"https://github.com","kind":"github","repositories_count":247289428,"owners_count":20914464,"icon_url":"https://github.com/github.png","version":null,"created_at":"2022-05-30T11:31:42.601Z","updated_at":"2022-07-04T15:15:14.044Z","host_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub","repositories_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories","repository_names_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repository_names","owners_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/owners"}},"keywords":["acid","btree","concurrency","cursor","database","durable","embedded-database","java","key-value-store","nosql","persistence","raft","replication","sorting","storage-engine","transaction","transactional","transactions"],"created_at":"2024-12-10T19:18:21.794Z","updated_at":"2025-12-18T00:03:23.265Z","avatar_url":"https://github.com/cojen.png","language":"Java","funding_links":[],"categories":[],"sub_categories":[],"readme":"[![Maven Central](https://img.shields.io/maven-central/v/org.cojen/tupl.svg?label=Maven%20Central)](https://central.sonatype.com/artifact/org.cojen/tupl)\n\nTuplDB is a high-performance, concurrent, transactional, scalable, low-level embedded database. Features include record-level locking, upgradable locks, deadlock detection, cursors, hot backups, striped files, encryption, replication, compression, nested transaction scopes, direct lock control, sorting, views, filters, transforms, unions, intersections, and full memory mapped support.\n\n* [Javadocs](https://tupl.cojen.org/javadoc/org.cojen.tupl/org/cojen/tupl/package-summary.html)\n* [FAQ](https://github.com/cojen/TuplDB/wiki/FAQ)\n* [Replication](https://github.com/cojen/TuplDB/wiki/Replication)\n\nTuplDB can be used directly, or it can be used for implementing a high-level database. TuplDB is\npowerful enough for supporting all the requirements of relational SQL databases as well as\nNoSQL databases. Because TuplDB doesn't impose any structure or encoding for data, a high-level\ndatabase is free to implement the most efficient format it requires.\n\nThe main entry point is the [Database](https://tupl.cojen.org/javadoc/org.cojen.tupl/org/cojen/tupl/Database.html) class. Here is a simple example for opening a non-durable database:\n\n```java\nvar config = new DatabaseConfig().maxCacheSize(100_000_000);\nDatabase db = Database.open(config);\n```\n\nTo open a durable database, a base file path must be provided. Database files are created\nusing the base as a prefix.\n\n```java\nvar config = new DatabaseConfig()\n    .baseFilePath(\"/var/lib/tupl\")\n    .cacheSize(100_000_000)\n    .durabilityMode(DurabilityMode.NO_FLUSH);\n\nDatabase db = Database.open(config);\n```\n\nNotice that a fixed cache size is set, and also notice the durability mode. A weak\n[durability mode](https://tupl.cojen.org/javadoc/org.cojen.tupl/org/cojen/tupl/DurabilityMode.html) improves\nthe performance of transactional changes, by not immediately flushing those\nchanges to the underlying files.\n\nSetting a fixed cache size is generally preferred over setting a maximum size, because it\npre-allocates the cache when the Database is opened. This allows any heap size limits to be\ndetected early, yielding an OutOfMemoryError. The default cache size is 1000\npages, and the default page size is 4096 bytes.\n\nBasic operations\n----------------\n\nA TuplDB instance manages a collection of [indexes](https://tupl.cojen.org/javadoc/org.cojen.tupl/org/cojen/tupl/Index.html), which are ordered mappings of `byte[]` keys to `byte[]` values.\n\n```java\nDatabase db = ...\n\n// Open an index, creating it if necessary.\nIndex userIx = db.openIndex(\"user\");\n```\n\nIndexes offer a low-level representation of data, and so applications which use them directly are\nresponsible for performing their own encoding.\n\n```java\n// Store a user in an auto-commit transaction.\nUser user = ...\nbyte[] userKey = encodeUserKey(user);\nbyte[] userValue = encodeUserValue(user);\nuserIx.store(null, userKey, userValue);\n```\n\nTo bundle multiple operations together, specify an explicit [transaction](https://tupl.cojen.org/javadoc/org.cojen.tupl/org/cojen/tupl/Transaction.html):\n\n```java\nIndex userByNameIx = ...\n\nbyte[] userNameKey = encodeUserName(user);\n\nTransaction txn = db.newTransaction();\ntry {\n    userIx.store(txn, userKey, userValue);\n    userByNameIx.store(txn, userNameKey, userKey);\n    txn.commit();\n} finally {\n    txn.reset();\n}\n```\n\nEntries can retrieved by [loading](https://tupl.cojen.org/javadoc/org.cojen.tupl/org/cojen/tupl/View.html#load-org.cojen.tupl.Transaction-byte:A-) them directly, or via a [cursor](https://tupl.cojen.org/javadoc/org.cojen.tupl/org/cojen/tupl/Cursor.html):\n\n```java\n// Find all users whose last name starts with 'J'.\nbyte[] startKey = encodeUserName(\"J\");\nbyte[] endKey = encodeUserName(\"K\");\n\n// Open a new cursor with an auto-commit transaction.\nCursor namesCursor = userByNameIx.newCursor(null);\ntry {\n    // Find names greater than or equal to the start key.\n    namesCursor.findGe(startKey);\n    byte[] nameKey;\n    while ((nameKey = namesCursor.key()) != null) {\n        byte[] userKey = namesCursor.value();\n        ...\n\n        // Move to next name, while still being less than the end key.\n        namesCursor.nextLt(endKey);\n    }\n} finally {\n    namesCursor.reset();\n}\n```\n\nThe above example can also be implemented using a sub-view:\n\n```java\n// View all users whose last name starts with 'J'.\nView userByNameView = userByNameIx.viewPrefix(startKey, 0);\n\n// Scan the entire view of names.\nCursor namesCursor = userByNameView.newCursor(null);\ntry {\n    namesCursor.first();\n    byte[] nameKey;\n    while ((nameKey = namesCursor.key()) != null) {\n        byte[] userKey = namesCursor.value();\n        ...\n\n        namesCursor.next();\n    }\n} finally {\n    namesCursor.reset();\n}\n```\n","project_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Fcojen%2Ftupldb","html_url":"https://awesome.ecosyste.ms/projects/github.com%2Fcojen%2Ftupldb","lists_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Fcojen%2Ftupldb/lists"}