可用于在低选择性列上选择记录的策略范围有哪些?
一个示例可能是订单表,多年来,您在其中建立了大量已完成的订单,但通常需要选择活动订单。订单可能会经历一个生命周期,例如下单、库存分配、从仓库挑选、发送给客户、开具发票和付款。订单还可能被取消、保留等。大多数记录最终将处于最终状态(例如已付款),但您可能经常需要选择(例如)已分配的订单。在这种情况下,顺序读取会很慢。
关于索引的类似问题
MySQL:低基数/选择性列=如何索引?
SQL 中索引很糟糕吗?
什么是索引以及如何使用它们来优化数据库中的查询?
定义索引:哪些列以及性能影响?
以及许多其他相关性逐渐减弱的因素。
我读过的方法(在 stackoverflow 和其他地方)包括
- 使用位图索引
- 使用部分索引 (
create index x on t(c2) where c1='a'
)
- 使用聚集索引?
- 不要索引低选择性列,使用顺序读取
- 将数据分区(例如,分成具有相同模式的多个表)
- 使用补充表(例如
active_customers(customer_id)
我当前的 DBMS 不支持上面列出的前三个选项,其余选项似乎有问题 - 还有其他常用的方法吗?
更新:我见过
- 为低选择性列建立索引,但仅选择高选择性值。
我同意无理的观点However分支。但关于此案,有一些事情需要了解。
这称为倾斜和倾斜杀死。这是部分索引的完美用途,您可以排除 95% 的已付发票,只对更有趣和更有选择性的统计数据建立索引。但你没有那个。您可以将所有行水平分区到单独的表/分区中,但随后您需要考虑行迁移(从一种状态移动到另一种状态),这是昂贵的。 DBMS 必须执行更新、删除和插入来更改状态。如果你的系统容量很大,那会很糟糕。
忘记您所说的是否基于选择性建立索引,因为将索引放在快速变化的列上通常也是一个坏主意。您的索引将包含热块,其中所有步骤 1 都将被删除,另一个热块将所有步骤 2 都插入其中,顺便说一句,某些步骤 2 将同时被删除到步骤 3 中。这不会很好地扩展。
我建议将您的状态垂直分区到单独的表中。
您的发票表将包含 PK 和除状态之外的所有列。
您可以通过两种方式处理您的状态。该表将包含返回到发票表的 FK 的 PK 值、状态以及您进入该状态时的时间戳。最好的是关于状态的水平分区表。您将为每种可能的状态都有一个分区。因此,找到所有或一个“已放置”状态将对分区进行修剪并仅读取它需要的分区 - 这是非常少量的块。由于该行非常窄,因此您可能会在一个块上获得 400 个发票状态。由于 PK 上有一个全局索引,因此查找任何一张发票的状态都很容易。
如果您的 RDBMS 不支持行迁移分区,您需要将这些分区作为表进行管理,并从一个分区中删除并插入到另一个分区中。您将把这些移动封装在过程的事务中,以便保持数据干净。每张发票都位于一个且仅有一个状态表中。更困难的部分是通过发票 ID 进行查询,您必须检查每个表以了解它在哪里。
你还有另一个选择您可以写付费状态,也可以不写。如果它是分区表,则当发票转为已付款状态时,您只需从发票状态表中删除发票即可。 (当然,您将向奖励材料中提到的历史表写入付费记录)。然后,您将对状态表进行外连接,空值表示已付款。如果您几乎从不查询付费状态,那么确实没有理由进行快速查询。
奖励材料
无论哪种情况,您都需要在报告表中跟踪这些变动。每次更新状态时,您都需要将其写入历史表。最终你会想要分析我所说的运输时间。从填补到付款的平均时间是多少(按月计算)?这是由于经济不景气而增加的吗?从放置到装满的运输时间是多少(按月)。夏季是否会因为假期失踪而需要更长的时间?你明白了。通过更新该列,您将丢失这些答案,因此您需要将该历史记录嵌入到您的过程中。
本文内容由网友自发贡献,版权归原作者所有,本站不承担相应法律责任。如您发现有涉嫌抄袭侵权的内容,请联系:hwhale#tublm.com(使用前将#替换为@)