低选择性色谱柱的索引和替代品

Red*_*ick 8 sql indexing database-design relational-database

在低选择性色谱柱上选择记录的策略范围有哪些?

一个示例可能是订单表,多年来,您构建了大量已完成的订单,但通常需要选择活动订单.订单可能会经历生命周期,例如放置,库存分配,从仓库中挑选,发送给客户,开具发票和付款.订单可能还会被取消,保留等.大多数记录最终将处于最终状态(例如已付款),但您可能经常需要选择已分配的订单.在这种情况下,顺序读取会很慢.

索引
MySQL的类似问题:低基数/选择性列=如何索引?
索引是否在SQL中吮吸?
什么是索引以及如何使用它们来优化数据库中的查询?
定义索引:哪些列和性能影响?
和其他许多其他相关的因素.

我读过的方法(在stackoverflow和其他地方)包括

  • 使用位图索引
  • 使用部分索引(create index x on t(c2) where c1='a')
  • 使用聚集索引?
  • 不要索引低选择性列,使用顺序读取
  • 对数据进行分区(例如,分成具有相同模式的多个表)
  • 使用补充表(例如 active_customers(customer_id)

我目前的DBMS不支持上面列出的前三个选项,其余的似乎有问题 - 还有其他常用的方法吗?

更新:我见过 - 索引低选择性列,但只选择高选择性值.

Ste*_*age 3

我同意 Unreason 的How分支。但关于此案,有一些事情需要了解。

这称为倾斜和倾斜杀死。这是部分索引的完美用途,您可以排除 95% 的已付发票,只对更有趣和更有选择性的统计数据建立索引。但你没有那个。您可以将所有行水平分区到单独的表/分区中,但随后您需要考虑行迁移(从一种状态移动到另一种状态),这是昂贵的。DBMS 必须执行更新、删除和插入来更改状态。如果你的系统容量很大,那会很糟糕。

忘记您所说的是否基于选择性建立索引,因为将索引放在快速变化的列上通常也是一个坏主意。您的索引将包含热块,其中所有步骤 1 都将被删除,另一个热块将所有步骤 2 都插入其中,顺便说一句,某些步骤 2 将同时被删除到步骤 3 中。这不会很好地扩展。

我建议将您的状态垂直分区到单独的表中。

您的发票表将包含 PK 和除状态之外的所有列。

您可以通过两种方式处理您的状态。该表将包含返回到发票表的 FK 的 PK 值、状态以及您进入该状态时的时间戳。最好的是关于状态的水平分区表。您将为每种可能的状态都有一个分区。因此,找到所有或一个“已放置”状态将对分区进行修剪并仅读取它需要的分区 - 这是非常少量的块。由于该行非常窄,因此您可能会在一个块上获得 400 个发票状态。由于 PK 上有一个全局索引,因此查找任何一张发票的状态都很容易。

如果您的 RDBMS 不支持行迁移分区,您需要将这些分区作为表进行管理,并从一个分区中删除并插入到另一个分区中。您将把这些移动封装在过程的事务中,以便保持数据干净。每张发票都位于一个且仅有一个状态表中。更困难的部分是通过发票 ID 进行查询,您必须检查每个表以了解它在哪里。

您还有另一种选择 您可以写付费状态,也可以不写。如果它是分区表,则当发票转为已付款状态时,您只需从发票状态表中删除发票即可。(当然,您将向奖励材料中提到的历史表写入付费记录)。然后,您将对状态表进行外连接,空值表示已付款。如果您几乎从不查询付费状态,那么确实没有理由进行快速查询。

奖励材料

无论哪种情况,您都需要在报告表中跟踪这些变动。每次更新状态时,您都需要将其写入历史表。最终你会想要分析我所说的运输时间。从填补到付款的平均时间是多少(按月计算)?这是由于经济不景气而增加的吗?从放置到装满的运输时间是多少(按月)。夏季是否会因为假期失踪而需要更长的时间?你明白了。通过更新该列,您将丢失这些答案,因此您需要将该历史记录嵌入到您的过程中。