- 当多次添加相同的 datoms 时,Datomic 会发生什么?
- 是否值得检查在事务之前已经添加了一个 datom ?
从逻辑上讲,一个 Datomic 数据库是一组有序的 datom,因此多次添加同一个 datom 是幂等的。但是,当您使用 tempid 断言 datom 时,您可以创建一个新 datom 来表示与旧 datom 相同的信息。这就是:db/unique
进来的地方。
为确保实体不会被多次存储,您需要将:db/unique
属性属性设置:db.unique/identity
为正确的属性。例如,如果您的架构包含 3 个属性:word/text
、:sentence/text
和:sentence/words
,那么:word/text
和:sentence/text
应该是:db.unique/identity
,这会产生以下架构安装事务:
[{:db/cardinality :db.cardinality/one,
:db/fulltext true,
:db/index true,
:db.install/_attribute :db.part/db,
:db/id #db/id[:db.part/db -1000777],
:db/ident :sentence/text,
:db/valueType :db.type/string,
:db/unique :db.unique/identity}
{:db/cardinality :db.cardinality/one,
:db/fulltext true,
:db/index true,
:db.install/_attribute :db.part/db,
:db/id #db/id[:db.part/db -1000778],
:db/ident :word/text,
:db/valueType :db.type/string,
:db/unique :db.unique/identity}
{:db/cardinality :db.cardinality/many,
:db/fulltext true,
:db/index true,
:db.install/_attribute :db.part/db,
:db/id #db/id[:db.part/db -1000779],
:db/ident :sentence/words,
:db/valueType :db.type/ref}]
然后插入插入的事务看起来像:
[{:sentence/text "Hello World!"
:sentence/words [{:word/text "hello"
:db/id (d/tempid :db.part/user)}
{:word/text "world"
:db/id (d/tempid :db.part/user)}]
:db/id (d/tempid :db.part/user)}]
关于性能:
您可能根本不需要优化,但在我看来,导入过程的潜在性能瓶颈是:
- 在 Transactor 中构建事务所花费的时间(包括唯一属性的索引查找等)
- 构建索引所花费的时间。
改进2.
:当你插入的数据被排序时,索引速度更快,所以将插入的单词和句子排序。您可以使用 Unix 工具对大文件进行排序,即使它们不适合内存。所以这个过程是:
- 排序句子,插入它们 (
:sentence/text
)
- 提取单词、排序、插入 (
:word/text
)
- 插入词句关系 (
:sentence/words
)
改进1.
:确实,它可以减轻交易者对已经存储的单词使用实体ID而不是整个单词文本的压力(这需要索引查找以确保唯一性)。一个想法可能是在 Peer 上执行该查找,或者通过利用并行性和/或仅针对常用词(例如,您可以插入前 1000 个句子中的词,然后检索它们的实体 ID 并将它们保存在哈希图中)。
就个人而言,除非经验表明它们是必要的,否则我不会进行这些优化。