u23*_*534 2 sql-server-2008 sql-server partitioning
我有以下分区表
create table T (Month char(6), ID int, .... primary key (ID, Month)) on psMonth(Month)
Run Code Online (Sandbox Code Playgroud)
分区函数是
CREATE PARTITION FUNCTION [pfMonth](char(6)) AS
RANGE RIGHT FOR VALUES (N'200001', .... N'200705', N'200706', N'200707', ....)
Run Code Online (Sandbox Code Playgroud)
但是,以下查询显示的实际分区数是 260 而不是 1?
select count(*)
from T (nolock)
where Month = '200706'
Run Code Online (Sandbox Code Playgroud)
执行计划是
|--计算标量(DEFINE:([Expr1004]=CONVERT_IMPLICIT(int,[globalagg1006],0)))
|--Stream Aggregate(DEFINE:([globalagg1006]=SUM([partialagg1005])))
|--Parallelism(Gather Streams)
|--Stream Aggregate(DEFINE:([partialagg1005]=Count(*)))
|--聚簇索引扫描(OBJECT:([DB].[dbo].[T].[PK_T]), WHERE:([DB].[dbo].[T].[Month]=[@1] ))
更新:如果我运行以下查询
,查询运行速度很快,实际分区计数为 1。
select count(*), $partition.pfMonth(Month)
from T with (nolock)
where Month = '200706'
group by $partition.pfMonth(Month)
Run Code Online (Sandbox Code Playgroud)
更新 2:
以下查询也只扫描一个分区。
select count(*), min($partition.pfByMonth(Month))
from T
where Month = '200707'
Run Code Online (Sandbox Code Playgroud)
更新 3:
原来的 SQL 现在只扫描一个分区。不知道发生了什么。唯一的区别是表中插入了更多数据。
答:我使用了包裹桌子的 CTE。它解决了由类型优先级引起的问题。(然而,CTE 一开始并没有解决这个问题,整个事情很奇怪而且不可预测。)
您的列的类型为CHAR(6)。您的过滤器属于类型VARCHAR(可能违反直觉,但常量文字'200706'是什么)。数据类型优先级的规则规定使用具有更高优先级的类型进行比较,即。VARCHAR 类型。这是与分区函数不同的类型,因此您不会进行分区消除。
试试这个:
select count(*)
from T (nolock)
where Month = CAST('200706' as CHAR(6));
Run Code Online (Sandbox Code Playgroud)
您的计划应该有一个分区消除过滤器。