Разделы таблицы SQL Azure Игнорируется, когда запросы содержат простую функцию - PullRequest
1 голос
/ 05 апреля 2019

Использование базы данных Azure SQL Server.У меня есть несколько таблиц, разделенных на 90-дневную границу даты.У нас есть хранимая процедура для смещения данных для поддержания правильной точки останова / диапазона раздела.Я использую небольшую функцию для обеспечения правильной точки прерывания по дате для моих запросов, поэтому мне не нужно постоянно обновлять все свои представления.

Но только благодаря использованию этой функции в моих запросах разбиение игнорируется.Разве у меня нет другого выбора, кроме как везде включать жестко запрограммированные значения в свои запросы и постоянно их изменять?

Вот пример, который воспроизводит проблему.

Обновление :После изменения функции PartitionDate, указанной ниже, в соответствии с помеченным ответом, все было хорошо в течение короткого времени (произошло удаление раздела).Затем запросы снова начали сосать.Когда я выполнял простые запросы, отфильтрованные функцией даты, разделы больше не удалялись.

------------------------------- setup
-- Create functions PartitionDate and PartitionQueryDate
create function PartitionDate() returns date as
begin
  return GETDATE() - 91 -- returns 1/4/2019 today
end
go
create function PartitionQueryDate() returns date as
begin
  return GETDATE() - 90 -- returns 1/5/2019
end
go

-- Create partition func and scheme using above functions
CREATE PARTITION FUNCTION order_pf (smalldatetime) AS RANGE RIGHT FOR VALUES (dbo.PartitionDate())
CREATE PARTITION SCHEME order_ps AS PARTITION order_pf ALL TO ([PRIMARY])

-- Create Order (pk, OrderDate, Fk), Customer (pk) tables.  Order is partitioned
create table Customer
(
    id int primary key identity(1,1), 
    FirstName varchar(255) not null
)
create table [Order]
(
    id int identity(1,1), OrderDate smalldatetime not null, 
    CustomerId int not null,
    CONSTRAINT [FK_Orders_Customer] FOREIGN KEY ([CustomerId]) REFERENCES Customer([id])
) on order_ps(OrderDate);

-- Add in indexes to Order: only OrderDate on the partition func
CREATE CLUSTERED INDEX [Order_OrderDate] ON [Order]([OrderDate] ASC) ON [order_ps] ([OrderDate]);
CREATE NONCLUSTERED INDEX [FK_Order_Customer] ON [Order](CustomerId, OrderDate) ON [order_ps] ([OrderDate]) -- seems to work the same with or without the partition reference.
go

-- Add some data before and after the partition break
insert Customer values ('bob')
insert [Order] values('12-31-2018', SCOPE_IDENTITY())
insert Customer values ('hank')
insert [Order] values('1-6-2019', SCOPE_IDENTITY())

---------------------------- test
-- verify a row per partition:
SELECT $PARTITION.order_pf(OrderDate) as Partition_Number, COUNT(*) as Row_Count 
FROM [Order]
GROUP BY $PARTITION.order_pf(OrderDate)

-- Simple queries with actual execution plan turned on.  The queries are logically equivalent.
select COUNT(1) from [Order] where OrderDate > '1-5-2019'   -- Index seek Order_OrderDate; actual partition count 1
select COUNT(1) from [Order] where OrderDate > dbo.PartitionQueryDate() -- Index seek Order_OrderDate; actual partition count 2

-- Cleanup
drop table if exists [Order]
drop table if exists Customer
drop partition scheme order_ps
drop partition function order_pf
drop function if exists PartitionDate
drop function if exists PartitionQueryDate

1 Ответ

0 голосов
/ 05 апреля 2019

Один из обходных путей - сначала назначить результат функции переменной.

declare @pqd smalldatetime = dbo.PartitionQueryDate();

select COUNT(1) from [Order] where OrderDate > @pqd

Другой вариант - использовать встроенный TVF

CREATE FUNCTION dbo.PartitionQueryDateTVF ()
RETURNS TABLE 
AS
RETURN 
(
    SELECT CAST(CAST( GETDATE() - 90 AS  DATE) AS SMALLDATETIME) AS Date
)

GO

SELECT COUNT(1) from [Order] where OrderDate > (SELECT Date FROM dbo.PartitionQueryDateTVF())

. Это может бытьулучшено с помощью встроенных скалярных UDF, но сейчас я не могу это проверить

...