SQL分区消除

时间:2011-09-22 16:00:33

标签: sql sql-server sql-server-2008 partitioning

我目前正在测试分区配置,使用实际执行计划来识别RunTimePartitionSummary / PartitionsAccessed信息。

当使用文字对分区列运行查询时,分区消除工作正常(使用=和< =)。但是,如果查询连接到查找表,则将分区列< =连接到查找表中的列,并使用其他条件限制查找表(以便只返回一行,就像它是文字一样) )消除不会发生。

如果连接条件是< =而不是=,这似乎只会发生,即使结果是相同的。颠倒逻辑并使用它们也不起作用,也不使用交叉应用函数。

编辑:( Repro Steps)

好的,你走了!

--Create sample function
CREATE PARTITION FUNCTION pf_Test(date) AS RANGE RIGHT FOR VALUES ('20110101','20110102','20110103','20110104','20110105') 
--Create sample scheme
CREATE PARTITION SCHEME ps_Test AS PARTITION pf_Test ALL TO ([PRIMARY])
--Create sample table
CREATE TABLE t_Test
    (
        RowID int identity(1,1)
        ,StartDate date NOT NULL
        ,EndDate date NULL
        ,Data varchar(50) NULL
    )
ON ps_Test(StartDate)
--Insert some sample data
INSERT INTO t_Test(StartDate,EndDate,Data)
VALUES
    ('20110101','20110102','A')
    ,('20110103','20110104','A')
    ,('20110105',NULL,'A')
    ,('20110101',NULL,'B')
    ,('20110102','20110104','C')
    ,('20110105',NULL,'C')
    ,('20110104',NULL,'D')

--Check partition allocation
SELECT *,$PARTITION.pf_Test(StartDate) AS PartitionNumber FROM t_Test

--Run simple test (inlcude actual execution plan)
SELECT 
    *
    ,$PARTITION.pf_Test(StartDate)
FROM t_Test
WHERE StartDate <= '20110103' AND ISNULL(EndDate,getdate()) >= '20110103'
--<PartitionRange Start="1" End="4" />

--Run test with join to a lookup (with CTE for simplicity, but doesnt work with table either)
WITH testCTE AS
    (
        SELECT convert(date,'20110101') AS CalendarDate,'A' AS SomethingInteresting
        UNION ALL
        SELECT convert(date,'20110102') AS CalendarDate,'B' AS SomethingInteresting
        UNION ALL
        SELECT convert(date,'20110103') AS CalendarDate,'C' AS SomethingInteresting
        UNION ALL
        SELECT convert(date,'20110104') AS CalendarDate,'D' AS SomethingInteresting
        UNION ALL
        SELECT convert(date,'20110105') AS CalendarDate,'E' AS SomethingInteresting
        UNION ALL
        SELECT convert(date,'20110106') AS CalendarDate,'F' AS SomethingInteresting
        UNION ALL
        SELECT convert(date,'20110107') AS CalendarDate,'G' AS SomethingInteresting
        UNION ALL
        SELECT convert(date,'20110108') AS CalendarDate,'H' AS SomethingInteresting
        UNION ALL
        SELECT convert(date,'20110109') AS CalendarDate,'I' AS SomethingInteresting
    )

SELECT
    C.CalendarDate
    ,T.*
    ,$PARTITION.pf_Test(StartDate)
FROM t_Test T
    INNER JOIN testCTE C
        ON T.StartDate <= C.CalendarDate AND ISNULL(T.EndDate,getdate()) >= C.CalendarDate
WHERE C.SomethingInteresting = 'C'    --<PartitionRange Start="1" End="6" />

--So all 6 partitions are scanned despite only 2,3,4 being required, as per the simple select. 

- 编辑以使结果范围相同以确保公平测试

1 个答案:

答案 0 :(得分:0)

查询扫描所有分区是有意义的。

所有分区都涉及谓词T.StartDate <= C.CalendarDate,因为查询计划程序无法知道C.CalendarDate可能采用的值。