Datahike数据库模式详解:从schema-on-read到schema-on-write
数据库模式概述
在现代数据库系统中,数据模式(Schema)是定义数据结构和约束的核心概念。Datahike作为一款灵活的持久化数据库,提供了两种截然不同的模式处理方式:schema-on-read(读时模式)和schema-on-write(写时模式)。这两种方式代表了数据库设计哲学的两种不同思路。
两种模式对比
schema-on-read模式
schema-on-read是一种灵活的数据处理方式,它允许在写入时不强制数据结构,而是在读取时解释数据。这种模式的特点包括:
- 灵活性高:可以存储任意结构的Clojure数据结构
- 无前期约束:不需要预先定义数据模型
- 适合快速原型开发:在项目初期数据结构频繁变化时特别有用
在Datahike中,这是从Datascript继承而来的默认行为。要启用这种模式,需要在创建数据库时显式设置:schema-flexibility参数为:read。
(def cfg {:store {:backend :mem :id "schemaless"}
:schema-flexibility :read})
schema-on-write模式
schema-on-write则采用了更为严格的数据管理方式,它要求:
- 预先定义模式:必须明确指定数据结构才能写入
- 数据完整性保证:数据库会强制执行定义的数据约束
- 更好的性能:预先知道数据结构可以优化存储和查询
从Datahike 0.2.0版本开始,schema-on-write成为默认模式。这种模式更接近传统关系型数据库的做法。
Datahike模式定义详解
在schema-on-write模式下,Datahike采用了与Datomic兼容的模式定义方式。每个属性必须定义三个核心特性:
- :db/ident:属性标识符,通常使用带命名空间的关键字
- :db/valueType:属性值的类型
- :db/cardinality:属性值的基数(单一值或多值)
完整属性定义示例
[{:db/ident :user/name
:db/valueType :db.type/string
:db/cardinality :db.cardinality/one
:db/doc "用户的全名"
:db/unique :db.unique/identity
:db/index true}]
支持的数据类型
Datahike支持丰富的数据类型,涵盖了大多数应用场景:
| 类型标识 | Java/Clojure类型 | 说明 |
|---|---|---|
| :db.type/bigdec | java.math.BigDecimal | 高精度十进制数 |
| :db.type/bigint | java.math.BigInteger | 大整数 |
| :db.type/boolean | Boolean | 布尔值 |
| :db.type/double | Double | 双精度浮点数 |
| :db.type/instant | java.util.Date | 时间戳 |
| :db.type/keyword | clojure.lang.Keyword | Clojure关键字 |
| :db.type/ref | java.lang.Long | 引用其他实体的ID |
| :db.type/tuple | clojure.lang.Vector | 向量形式的元组 |
高级模式特性
除了基本定义外,Datahike还支持一些高级模式特性:
- 唯一性约束:通过
:db/unique确保属性值的唯一性 - 索引:通过
:db/index为属性创建索引提高查询性能 - 组件关系:通过
:db/isComponent定义组件引用关系 - 元组类型:支持复合元组、异构元组等多种元组形式
模式迁移策略
在Datahike中,模式一旦定义就不建议直接修改。这是因为:
- 数据一致性风险:模式变更可能导致现有数据不一致
- 有限支持:仅支持基数(:db/cardinality)和唯一性(:db/unique)的变更
推荐的模式迁移方式是:
- 创建新属性而非修改现有属性
- 编写数据迁移脚本将旧数据转换到新属性
- 或者导出数据后重建数据库
最佳实践建议
- 项目初期:可以使用schema-on-read快速迭代
- 生产环境:推荐使用schema-on-write确保数据完整性
- 文档化:充分利用
:db/doc为属性添加说明 - 索引策略:为常用查询条件创建索引
- 命名规范:使用命名空间关键字(:namespace/name)避免命名冲突
Datahike的模式系统提供了强大的数据建模能力,同时保持了足够的灵活性。理解并合理运用这些特性,可以构建出既健壮又易于维护的数据层。
创作声明:本文部分内容由AI辅助生成(AIGC),仅供参考



