一个 SQLite 扩展,用于生成和处理 ULID。构建于 sqlite-loadable-rs 和 ulid-rs 之上。
如果您的公司或组织觉得这个库很有用,请考虑支持我的工作!
.load ./ulid0
select ulid(); -- '01gqr4j69cc7w1xdbarkcbpq17'
select ulid_bytes(); -- X'0185310899dd7662b8f1e5adf9a5e7c0'
select ulid_with_prefix('invoice'); -- 'invoice_01gqr4jmhxhc92x1kqkpxb8j16'
select ulid_with_datetime('2023-01-26 22:53:20.556); -- '01gqr4j69cc7w1xdbarkcbpq17'
select ulid_datetime('01gqr4j69cc7w1xdbarkcbpq17') -- '2023-01-26 22:53:20.556'
用作表的 PRIMARY KEY
(主键)。
create table log_events(
id ulid primary key,
data any
);
insert into log_events(id, data) values (ulid(), 1);
insert into log_events(id, data) values (ulid(), 2);
insert into log_events(id, data) values (ulid(), 3);
select * from log_events;
/*
┌────────────────────────────┬──────┐
│ id │ data │
├────────────────────────────┼──────┤
│ 01gqr4vr487bytsf10ktfmheg4 │ 1 │
│ 01gqr4vr4dfcfk80m2yp6j866z │ 2 │
│ 01gqr4vrjxg0yex9jr0f100v1c │ 3 │
└────────────────────────────┴──────┘
*/
考虑使用 ulid_bytes()
以提高速度和获得更小的 ID。它们的生成速度比 ulid()
快约 1.6 倍,并且占用 16 字节而不是 26 字节。您可以使用 ulid()
创建 BLOB ULID 的文本表示。
create table log_events(
id ulid primary key,
data any
);
insert into log_events(id, data) values (ulid_bytes(), 1);
insert into log_events(id, data) values (ulid_bytes(), 2);
insert into log_events(id, data) values (ulid_bytes(), 3);
select hex(id), ulid(id), data from log_events;
/*
┌──────────────────────────────────┬────────────────────────────┬──────┐
│ hex(id) │ ulid(id) │ data │
├──────────────────────────────────┼────────────────────────────┼──────┤
│ 0185F0539EBF286DA9F56BA4D9981783 │ 01gqr577nz51ptkxbbmkcsg5w3 │ 1 │
│ 0185F0539EC54F85745C1ECB64DF3A97 │ 01gqr577p59y2q8q0ysdjdyemq │ 2 │
│ 0185F0539ED48113F6F67BF3F6A4BFF7 │ 01gqr577pmg49zdxkvyfva9fzq │ 3 │
└──────────────────────────────────┴────────────────────────────┴──────┘
*/
使用 ulid_datetime()
提取 ULID 的时间戳部分。
select ulid_datetime(ulid()); -- '2023-01-26 23:07:36.508'
select unixepoch(ulid_datetime(ulid())); -- 1674774499
select strftime('%Y-%m-%d', ulid_datetime(ulid())); -- '2023-01-26''
考虑使用 ulid_with_prefix()
生成带有给定前缀的文本 ULID,以区分不同类型的 ID。
select ulid_with_prefix('customer'); -- 'customer_01gqr5j1ebk31wv30wgp8ebehj'
select ulid_with_prefix('product'); -- 'product_01gqr5prjgsa77dhrxf2dt1dgv'
select ulid_with_prefix('order'); -- 'order_01gqr5q35n68jk0sycy1ntr083'
并非最终结果,在 Macbook 上匆忙运行,不代表实际使用场景。uuid()
SQL 函数来自 官方的 uuid.c
扩展。
测试用例 | 时间 |
---|---|
generate_series() 生成 100 万行 |
28.5 毫秒 ± 0.8 毫秒 (1 倍 ) |
调用 ulid_bytes() 100 万次 |
88.4 毫秒 ± 2.8 毫秒 ,慢 3.10 ± 0.13 倍 |
调用 uuid() 100 万次 |
141.6 毫秒 ± 1.5 毫秒 ,或慢 4.97 ± 0.15 倍 |
调用 ulid() 100 万次 |
344.3 毫秒 ± 11.9 毫秒 ,或慢 12.07 ± 0.53 倍 |
因此 ulid_bytes()
速度相当快,但返回的是不可读的 BLOB,而不是格式良好的文本 ID。ulid()
函数可以返回文本 ID,但速度比 uuid()
慢两倍以上。
然而,在约 350 毫秒内生成 100 万个 ulid()
ID 对于大多数 SQLite 用例来说很可能“足够好”了。
语言/环境 | 安装 | |
---|---|---|
Python | pip install sqlite-ulid |
|
Datasette | datasette install datasette-sqlite-ulid |
|
Node.js | npm install sqlite-ulid |
|
Deno | deno.land/x/sqlite_ulid |
|
Ruby | gem install sqlite-ulid |
|
Rust | cargo add sqlite-ulid |
|
Github 发布页 |
发布页包含适用于 Linux x86_64、MacOS 和 Windows 的预构建二进制文件。
对于 Python 开发者,可以使用以下命令安装 sqlite-ulid
包:
pip install sqlite-ulid
import sqlite3
import sqlite_ulid
db = sqlite3.connect(':memory:')
db.enable_load_extension(True)
sqlite_ulid.load(db)
db.execute('select ulid()').fetchone()
# ('01gr7gwc5aq22ycea6j8kxq4s9',)
更多详细信息请参阅 python/sqlite_ulid
。
对于 Node.js 开发者,可以使用以下命令安装 sqlite-ulid
npm 包:
npm install sqlite-ulid
import Database from "better-sqlite3";
import * as sqlite_ulid from "sqlite-ulid";
const db = new Database(":memory:");
db.loadExtension(sqlite_ulid.getLoadablePath());
更多详细信息请参阅 npm/sqlite-ulid/README.md
。
对于 Deno 开发者,请使用 deno.land/x/sqlite_ulid 模块:
import { Database } from "https://deno.land/x/sqlite3@0.8.0/mod.ts";
import * as sqlite_ulid from "https://deno.land/x/sqlite_ulid@v${VERSION}/mod.ts";
const db = new Database(":memory:");
db.enableLoadExtension = true;
sqlite_ulid.load(db);
const [version] = db.prepare("select ulid_version()").value<[string]>()!;
console.log(version);
对于 Datasette,可以使用以下命令安装 datasette-sqlite-ulid
插件:
datasette install datasette-sqlite-ulid
更多详细信息请参阅 python/datasette_sqlite_ulid
。
如果您想将 sqlite-ulid
用作运行时可加载扩展,请从发布页下载 ulid0.dylib
(用于 MacOS)、ulid0.so
(用于 Linux)或 ulid0.dll
(用于 Windows)文件,并将其加载到您的 SQLite 环境中。
注意:文件名中的
0
(ulid0.dylib
/ulid0.so
/ulid0.dll
)表示sqlite-ulid
的主版本号。目前sqlite-ulid
处于 v1 之前,因此未来版本可能会有重大更改。
例如,如果您使用SQLite 命令行界面,您可以按如下方式加载库:
.load ./ulid0
select ulid_version();
-- v0.1.0
在 Python 中,您应该首选 sqlite-ulid
Python 包。但是,您也可以使用内置的 sqlite3 模块手动加载预编译扩展:
import sqlite3
con = sqlite3.connect(":memory:")
con.enable_load_extension(True)
con.load_extension("./ulid0")
print(con.execute("select ulid_version()").fetchone())
# ('v0.1.0',)
或者在 Node.js 中使用 better-sqlite3:
const Database = require("better-sqlite3");
const db = new Database(":memory:");
db.loadExtension("./ulid0");
console.log(db.prepare("select ulid_version()").get());
// { 'ulid_version()': 'v0.1.0' }
使用 Datasette 时,您应该首选 datasette-sqlite-ulid
Datasette 插件。但是,您也可以像这样将预编译扩展手动加载到 Datasette 实例中:
datasette data.db --load-extension ./ulid0
我(Alex 👋🏼)在这个项目和许多其他开源项目上花费了大量时间和精力。如果您的公司或组织使用这个库(或者您乐于助人),请考虑支持我的工作,或者将这个项目分享给朋友!
- sqlite-xsv,一个用于处理 CSV 的 SQLite 扩展
- sqlite-loadable,一个用 Rust 编写 SQLite 扩展的框架
- sqlite-http,一个用于发出 HTTP 请求的 SQLite 扩展