【发布时间】:2020-02-21 18:46:19
【问题描述】:
在我们的 SQL Server 数据库中,我们有一个按日期列分区的表。 对于每个日期,我们插入了 50 万条记录。我们注意到查询性能很好 更接近分区开始范围的日期,并且随着每个日期的前进逐渐降级。
这是我的分区函数
CREATE PARTITION FUNCTION partition_position_monthly (DATE)
AS RANGE RIGHT FOR VALUES ('2019-09-01', '2019-11-01');
表格
CREATE TABLE PartitionTest(
ID int IDENTITY(1,1) NOT NULL,
col1 varchar(256) ,
col2 varchar(128) ,
col3 varchar(128) ,
BusinessDate date , -- partition column
) ON partition_scheme_monthly(BusinessDate)
BusinessDate 列上有一个聚集索引。
这是使用的查询
select top 1000 * from PartitionTest where BusinessDate = ?
每个营业日期的 CPU 和 IO 记录
营业日期 = 2019-09-01 CPU 时间 = 31 毫秒 扫描计数 1,逻辑读取 80,物理读取 0,,预读读取 0
营业日期 = 2019-09-02 CPU 时间 = 63 毫秒 扫描计数 1,逻辑读取 24905,物理读取 0,预读读取 3131
营业日期 = 2019-09-03 CPU 时间 = 125 毫秒 扫描计数 1,逻辑读取 49727,物理读取 0,预读读取 7
营业日期 = 2019-09-04 CPU 时间 = 172 毫秒 扫描计数 1,逻辑读取 74551,物理读取 0,预读读取 7
营业日期 = 2019-09-05 CPU 时间 = 234 毫秒 扫描计数 1,逻辑读取 99376,物理读取 0,预读读取 117
如您所见,BusinessDates 的 CPU 时间和逻辑读取数逐渐增加 离分区起始范围较远。
这是从分区获取数据时的预期行为吗?
我们计划对月度数据进行分区,接近月底的日子的查询响应时间超出了我们可接受的限制。有没有办法在分区中实现恒定的 CPU 时间和每天的逻辑读取?
【问题讨论】:
-
分区是一种数据管理功能,而不是性能功能。如果查询必须搜索多个分区,性能会下降。在这种情况下,您是否真的试图一次读取 500K 行?这是否意味着一个月包含 1500 万行?由于选择性如此低,
BusinessDate索引不是很有用 -
此测试一次只读取给定日期的前 1000 行。我们的查询总是获取单个业务日期的数据,因此我们不会跨分区搜索数据。奇怪的是逻辑读取的数量在接下来的每一天都在不断增加。 sql server 没有随机访问工具来读取分区内日期的数据。为什么一定要从文件开头依次开始?
-
前 1000 名是按什么顺序排列的?如果只使用
BusinessDate作为聚集键,则表示其余行是随机排列的。每个日期有 500K 行,服务器很可能决定使用并行执行计划 - 顺便说一句,您没有发布执行计划。在任何情况下,逻辑读取都是logical——它们读取的是缓存,而不是文件。就好像根本没有使用 BusinessDate 索引 - 或者服务器决定,因为它必须查找 1/60 的数据,所以进行扫描比查找要快 -
上传你的实际计划到brentozar.com/pastetheplan。
-
请发布执行计划。我敢打赌,糟糕的选择性
select *和数据大小会导致并行化表扫描,因为索引不包含所有字段,因此使用它会更昂贵。这将在执行计划中显而易见。如果聚集索引是 ID 并为 Date 加上一个额外的索引,那可能会更好。您还可以使用聚集列存储索引,它本质上是索引并压缩整个表。
标签: sql-server database-performance database-partitioning