一个示例可能是订单表,多年来,您构建了大量已完成的订单,但通常需要选择活动订单.订单可能会经历生命周期,例如放置,库存分配,从仓库中挑选,发送给客户,开具发票和付款.订单可能会被取消,保留等等.大多数记录最终将处于最终状态(例如付费),但您可能经常需要选择分配的订单.在这种情况下,顺序读取会很慢.
关于索引的类似问题
MySQL: low cardinality/selectivity columns = how to index?
Do indexes suck in SQL?
What are indexes and how can I use them to optimize queries in my database?
Defining indexes: Which Columns,and Performance Impact?
和其他许多其他相关的因素.
>使用位图索引
>使用部分索引(在t(c2)上创建索引x,其中c1 =’a’)
>使用聚集索引?
>不要索引低选择性列,使用顺序读取
>对数据进行分区(例如,分成具有相同模式的多个表)
>使用补充表格(例如active_customers(customer_id)
我目前的DBMS不支持上面列出的前三个选项,其余的似乎有问题 – 还有其他常用的方法吗?
更新:我见过
– 索引低选择性列,但只选择高选择性值.
解决方法
这称为歪斜和歪斜杀戮.这是部分索引的完美用途,您可以排除95%的付费发票,并仅索引更有趣和有选择性的统计数据.但你没有那个.您可以将所有行水平分区为单独的表/分区,但是您需要考虑行迁移(从一个状态移动到另一个状态),这很昂贵. DBMS必须执行更新,删除和插入以更改状态.如果你是一个会伤害的高容量系统.
忘记你所说的是否基于选择性进行索引,因为在快速变化的列上放置索引通常也是一个坏主意.您的索引将具有热块,其中所有步骤1被移除,而另一个步骤2的所有步骤被插入,而且,顺便说一下,某些步骤2将被同时移除到步骤3中.这不会很好地扩展.
我建议将您的状态垂直分区到一个单独的表中.
您的发票表将包含PK以及除状态之外的所有列.
您的状态可以通过两种方式处理.该表将PK值作为FK返回到发票表,状态和您输入该状态时的时间戳.最好的是状态上的水平分区表.您将为每种状态分配一个分区.因此,找到所有或一个“已放置”状态将分区修剪并只读取它所需的分区 – 这是一个非常少的块.由于行太窄,因此您可能会在一个块上获得400个发票状态.查看任何一张发票的状态很容易,因为PK上有一个全局索引.
如果您的RDBMS不支持使用行迁移进行分区,则需要将这些分区作为表进行管理,然后从一个分区中删除并插入另一个分区.您将这些移动封装在过程中的事务中,因此您可以保持数据清洁.每张发票都在一个且只有一个状态表中.更难的部分是按发票ID查询,您必须检查每张表以查看它的位置.
你有另一种选择
您可以编写付费状态.如果它是分区表,您只需在发票状态表中移动到付款时删除该发票. (当然,您可以将付费记录写入奖励材料中提到的历史记录表).然后你将对状态表进行外连接,并且null表示已付费.如果您几乎从不查询付费状态,那么实际上没有理由进行快速查询.
奖金材料
在任何一种情况下,您都希望在报告表中跟踪这些移动.每次更新状态时,您都希望将其写入历史记录表.最后,您需要分析我称之为运输时间的内容.按月填写到付费的平均时间是多少?由于经济不景气,这种情况会增加吗?从月份到装满的运输时间是多少.由于度假时身体缺失,夏季月份需要更长时间吗?你明白了.通过更新该列,您将丢失这些答案,因此您需要将该历史记录日志嵌入到您的过程中.