Медленная производительность запросов из-за разделов

В 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) on PartitionScheme([DateAndTime])
)

Запрос А:

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

Запрос Б:

-- 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

Оба запроса возвращают правильные результаты, но первый выполняет очень неэффективный план запроса, в котором, похоже, не учитывается тот момент, что все даты в декабрьских разделах будут > ноябрьских разделов и т. д. и т. п.

«Все типы данных допустимы для использования в качестве столбцов секционирования, за исключением text, ntext, image, xml, timestamp, varchar(max), nvarchar(max), varbinary(max), псевдонимов типов данных или пользовательских типов данных CLR. " Learn.microsoft.com/en-us/sql/t-sql/statements/…

Charlieface 31.05.2024 14:17
ReactJs | Supabase | Добавление данных в базу данных
ReactJs | Supabase | Добавление данных в базу данных
Это и есть ваш редактор таблиц в supabase.👇
Понимание Python и переход к SQL
Понимание Python и переход к SQL
Перед нами лабораторная работа по BloodOath:
1
1
72
1
Перейти к ответу Данный вопрос помечен как решенный

Ответы 1

Ответ принят как подходящий

Я понятия не имею, почему вы просто не используете datetime2 здесь и не используете свою собственную схему кодирования даты и времени как целые числа, но в любом случае вам следует использовать

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

Литералы 2412230000000000000 и т. д. decimal(19,0) не bigint определены в функции разделения, а несоответствие типов данных приводит к добавлению дополнительных операторов и увеличению вероятности менее эффективного плана.

При этом я получаю план, который посещает только 11 ожидаемых разделов, пронумерованных от 3 до 13 (как того требует BETWEEN $PARTITION.PartitionFunction(2402110000000000000) AND $PARTITION.PartitionFunction(2412230000000000000)), и без оператора сортировки.

(В отличие от этого плана с несовпадающими типами данных)

Спасибо большое, это полностью решило проблему. Есть причина не использовать DateTime, которую я указал по причинам IP.

Someone 01.06.2024 05:23

Другие вопросы по теме