你能帮我理解我在这篇文档中读到的内容吗?https://crate.io/docs/reference/sql/partitioned_tables.html
在这些示例表中,列id long
不是primary_key
;事实上,id
在这里不可能是主键,因为如下所述"如果设置了主键,它必须存在于PARTITION BY
子句中">
在我的应用程序中,我以前在id string NOT NULL
上有一个primary key
,但现在我想在这个表上,在生成的日期列上添加分区,就像在示例partition_date timestamp GENERATED ALWAYS AS date_trunc('day', created_at)
中一样。我读到过,在日期列上进行分区将有助于提高按时间段划分的查询速度(例如,计算今天的所有记录只会命中今天的分区),并帮助我归档较旧的数据帧(例如,任何大于180天的数据),但我不想失去单个PK查找的性能。
既然我不能只做PARTITIONED BY (partition_date)
,那么如果我…最好吗
a) 是否从id
中删除主键约束?我担心这会影响我的单行查找性能!在这种情况下,PK必须在分区键中是有意义的,因为查找WHERE id = "abc-123"
理想情况下只需命中单个节点。
或
b) 使用这两列作为分区键,比如PARTITIONED BY (id, partition_date)
——这看起来很奇怪,因为我本能地想假设id
的基数很高,对于分区列来说是个糟糕的选择,而"day"或"month"会更好,就像文档中的示例所示。在这种情况下,我的PK查找是否命中了每个分区,或者它确切地知道该去哪里?如果我只运行一个范围到今天的聚合查询,它会命中每个分区还是只命中保存今天数据的分区?
所以这是一个很好的问题!由于分区是排序的"子表",这有助于减少查询数据的大小。
主键会影响CrateDB中的路由,因此将其添加到分区表(需要更广泛的路由)将拒绝partitionby子句中的任何非主键列。因此,您的选择如下:
- a)虽然这消除了有效进行PK查找的能力,但这似乎是一个明智的选择-可以通过使用全文索引来加速常规字符串查找-但它也将删除写后读取一致主键查找添加。根据生成主键的方式,可以使用内部
_id
列(用于查找),或者在id查找之前发出REFRESH TABLE
- b) 将产生与主键一样多的分区(并且由于它们是唯一的…)-因此此选项将创建太多的分区
由于选项b)会导致混乱,我推荐选项a)。然而,如果主键查找对您的应用程序至关重要,并且预期的数据量不是那么大(当然,几百万也可以,这取决于集群大小和机器规格),那么在没有分区的情况下,它可能会正常工作!
干杯,克劳斯