我将应用程序从具有单个事件表的模式迁移到具有0.5到13亿条记录到partitioned views的单个事件表,其中30-180个相同的基础表,每个表都包含该记录数的一小部分大大缓解了管理和查询的一些问题 那么多记录。我使用分区视图而不是表分区,因为并非所有用户都可以访问SQL Server 2012的Awesome Edition。
分区功能基于事件当天的笛卡尔积和事件的一个属性。换句话说,2015年6月1日的所有事件都带有属性" foo"进入了一个类似" Event20150601_foo"的表格,所有具有属性" bar"的事件进入" Event20150601_bar"第二天,活动将进入" Event20150602_foo"和" Event20150602_bar"等。通常有2-3个属性值和15-60天的事件,它们映射到30-180个不同表的典型范围。
每个表的基本结构是一个复合聚簇主键,由EventId(bigint)和PartitionKey(int)组成,后跟少量其他未编制索引的列。 EventId是唯一的,在所有表中单调递增,并使用序列实现。 PartitionKey对于每个分区表是唯一的,因此每个表上的检查约束只是" CHECK(PartitionKey = x)"其中x是按分区表定义的。这允许我通过聚簇索引搜索在EventId上搜索,即使我无法提供分区键来缩小搜索范围。在我可以的情况下 提供EventId和PartitionKey,查询非常有效,因为优化器然后只能在匹配分区键的单个表上执行索引搜索,这是一个很大的性能获胜。
如果我能根据活动当天以及更广泛的属性组合(500-5000而不是前面提到的2-3)进行更细化和分区,这将使我的生活变得更加轻松,这将需要我具有10,000-50,000个不同的分区。我在一个包含20,000个不同表的数据库上对此进行了测试,不幸的是,发现不同操作的运行时间比表的数量大于线性速率。根据查询统计信息,大部分时间都花在解析和编译查询上,而不是执行查询。
以下是我为不同操作找到的运行时间(原谅基本表):
100 tables : 50ms
1000 tables : 800ms
2000 tables : 2,660ms
4000 tables : 10,000ms
16000 tables: 225,000ms
select * from PartitionedView where EventId = x
(扫描所有表格)
100 tables : 78ms parse/compile time; 25ms exec time
1000 tables : 3,500ms parse/compile time; 160ms exec time
2000 tables : 15,000ms parse/compile time; 500ms exec time
4000 tables : 68,000ms parse/compile time; 2,000ms exec time
16000 tables:
在>之后取消10分钟解析/编译时间!select * from PartitionedView where (EventId = x) and (PartitionKey = y)
(仅扫描一张表)
100 tables : 74ms parse/compile time; 1ms exec time
1000 tables : 2,500ms parse/compile time; 15ms exec time
2000 tables : 11,000ms parse/compile time; 10ms exec time
4000 tables : 50,000ms parse/compile time; 16ms exec time
16000 tables:
在>之后取消10分钟解析/编译时间!即使考虑使用那么多表,我还应该被责骂吗?如果没有,有没有办法可以减少查询解析&存在大量表格时的编译时间?