由于分区导致查询性能缓慢

问题描述 投票:0回答:1

在 SQL Server 中,查询 B 的执行速度比查询 A 快数百倍。总共只有 12 个分区。如何让查询B像查询A一样简单,同时又保持性能?

相关SQL语句:

CREATE PARTITION FUNCTION PartitionFunction (bigint)
AS RANGE RIGHT
FOR VALUES ( 
2401010000000000000,
2402010000000000000,
2403010000000000000,
2404010000000000000,
2405010000000000000,
2406010000000000000,
2407010000000000000,
2408010000000000000,
2409010000000000000,
2410010000000000000,
2411010000000000000,
2412010000000000000
)

CREATE PARTITION SCHEME PartitionScheme
AS PARTITION PartitionFunction 
ALL TO ([PRIMARY])

CREATE TABLE [dbo].[EmailIdx]
(
    [Email] [varchar](255) NOT NULL,
    [DateAndTime] [bigint] NOT NULL,
    [Serial] [bigint] NOT NULL,

    CONSTRAINT [PK_Email] 
        PRIMARY KEY CLUSTERED ([Email] ASC, [DateAndTime] ASC, [Serial] ASC)
                WITH (PAD_INDEX = OFF, STATISTICS_NORECOMPUTE = OFF, 
                      IGNORE_DUP_KEY = OFF, ALLOW_ROW_LOCKS = ON, 
                      ALLOW_PAGE_LOCKS = ON, OPTIMIZE_FOR_SEQUENTIAL_KEY = OFF)
)

查询A:

SELECT TOP 20
    Email,
    DateAndTime,
    Serial
FROM 
    EmailIdx WITH (NOLOCK)
WHERE
    Email = '[email protected]'
    AND DateAndTime < 2412230000000000000
    AND DateAndTime > 2402110000000000000 
ORDER BY 
    DateAndTime DESC

查询B:

-- Union all partitions from February to December starting from December
WITH CombinedResults AS 
(
    SELECT TOP 20
        Email,
        DateAndTime,
        Serial
    FROM 
        EmailIdx WITH (NOLOCK)
    WHERE
        $PARTITION.PartitionFunction(DateAndTime) = 12
        AND Email = '[email protected]'
        AND DateAndTime < 2412230000000000000
        AND DateAndTime > 2402110000000000000 
    ORDER BY 
        DateAndTime DESC

    UNION ALL

    SELECT TOP 20
        Email,
        DateAndTime,
        Serial
    FROM 
        EmailIdx WITH (NOLOCK)
    WHERE
        $PARTITION.PartitionFunction(DateAndTime) = 11
        AND Email = '[email protected]'
        AND DateAndTime < 2412230000000000000
        AND DateAndTime > 2402110000000000000 
    ORDER BY 
        DateAndTime DESC

    UNION ALL    

    SELECT TOP 20
        Email,
        DateAndTime,
        Serial
    FROM 
        EmailIdx WITH (NOLOCK)
    WHERE
        $PARTITION.PartitionFunction(DateAndTime) = 10
        AND Email = '[email protected]'
        AND DateAndTime < 2412230000000000000
        AND DateAndTime > 2402110000000000000 
    ORDER BY 
        DateAndTime DESC

    UNION ALL    

    SELECT TOP 20
        Email,
        DateAndTime,
        Serial
    FROM 
        EmailIdx WITH (NOLOCK)
    WHERE
        $PARTITION.PartitionFunction(DateAndTime) = 9
        AND Email = '[email protected]'
        AND DateAndTime < 2412230000000000000
        AND DateAndTime > 2402110000000000000 
    ORDER BY 
        DateAndTime DESC

    UNION ALL    

    SELECT TOP 20
        Email,
        DateAndTime,
        Serial
    FROM 
        EmailIdx WITH (NOLOCK)
    WHERE
        $PARTITION.PartitionFunction(DateAndTime) = 8
        AND Email = '[email protected]'
        AND DateAndTime < 2412230000000000000
        AND DateAndTime > 2402110000000000000 
    ORDER BY 
        DateAndTime DESC

    UNION ALL    

    SELECT TOP 20
        Email,
        DateAndTime,
        Serial
    FROM 
        EmailIdx WITH (NOLOCK)
    WHERE
        $PARTITION.PartitionFunction(DateAndTime) = 7
        AND Email = '[email protected]'
        AND DateAndTime < 2412230000000000000
        AND DateAndTime > 2402110000000000000 
    ORDER BY 
        DateAndTime DESC

    UNION ALL    

    SELECT TOP 20
        Email,
        DateAndTime,
        Serial
    FROM 
        EmailIdx WITH (NOLOCK)
    WHERE
        $PARTITION.PartitionFunction(DateAndTime) = 6
        AND Email = '[email protected]'
        AND DateAndTime < 2412230000000000000
        AND DateAndTime > 2402110000000000000 
    ORDER BY 
        DateAndTime DESC

    UNION ALL    

    SELECT TOP 20
        Email,
        DateAndTime,
        Serial
    FROM 
        EmailIdx WITH (NOLOCK)
    WHERE
        $PARTITION.PartitionFunction(DateAndTime) = 5
        AND Email = '[email protected]'
        AND DateAndTime < 2412230000000000000
        AND DateAndTime > 2402110000000000000 
    ORDER BY 
        DateAndTime DESC

    UNION ALL    

    SELECT TOP 20
        Email,
        DateAndTime,
        Serial
    FROM 
        EmailIdx WITH (NOLOCK)
    WHERE
        $PARTITION.PartitionFunction(DateAndTime) = 4
        AND Email = '[email protected]'
        AND DateAndTime < 2412230000000000000
        AND DateAndTime > 2402110000000000000 
    ORDER BY 
        DateAndTime DESC

    UNION ALL    

    SELECT TOP 20
        Email,
        DateAndTime,
        Serial
    FROM 
        EmailIdx WITH (NOLOCK)
    WHERE
        $PARTITION.PartitionFunction(DateAndTime) = 3
        AND Email = '[email protected]'
        AND DateAndTime < 2412230000000000000
        AND DateAndTime > 2402110000000000000 
    ORDER BY 
        DateAndTime DESC

    UNION ALL    

    SELECT TOP 20
        Email,
        DateAndTime,
        Serial
    FROM 
        EmailIdx WITH (NOLOCK)
    WHERE
        $PARTITION.PartitionFunction(DateAndTime) = 2
        AND Email = '[email protected]'
        AND DateAndTime < 2412230000000000000
        AND DateAndTime > 2402110000000000000 
    ORDER BY 
        DateAndTime DESC
)
SELECT TOP 20
    Email,
    DateAndTime,
    Serial
FROM 
    CombinedResults

两个查询都返回正确的结果,但第一个查询运行非常低效的查询计划,似乎忽略了 12 月分区中的所有日期将 > 11 月分区等这一点。

sql sql-server performance query-optimization
1个回答
0
投票

使用

WHERE
    Email = '[email protected]'
    AND DateAndTime < CAST(2412230000000000000 AS BIGINT)
    AND DateAndTime > CAST(2402110000000000000 AS BIGINT)

文字

2412230000000000000
等是
decimal
而不是
bigint
并且数据类型不匹配导致计划效率较低。

enter image description here

© www.soinside.com 2019 - 2024. All rights reserved.