Warning: file_get_contents(/data/phpspider/zhask/data//catemap/7/elixir/2.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
Sql server 查询包含简单函数时忽略Azure SQL表分区_Sql Server_Azure Sql Database_Database Partitioning - Fatal编程技术网

Sql server 查询包含简单函数时忽略Azure SQL表分区

Sql server 查询包含简单函数时忽略Azure SQL表分区,sql-server,azure-sql-database,database-partitioning,Sql Server,Azure Sql Database,Database Partitioning,使用Azure SQL Server数据库。我在90天的日期边界上划分了几个表。我们有一个存储过程来移动数据以保持适当的分区断点/范围。我正在使用一个小函数为我的查询提供合适的日期断点,这样我就不必不断更新我的所有视图 但由于在查询中使用了该函数,分区被忽略了。我是否别无选择,只能将硬编码的值放在查询中的任何地方并不断修改它们 这是一个重现问题的示例 更新:根据标记的答案更改下面的PartitionDate函数后,在短时间内一切正常(发生分区消除)。然后,查询又开始变得糟糕。当我运行由date函

使用Azure SQL Server数据库。我在90天的日期边界上划分了几个表。我们有一个存储过程来移动数据以保持适当的分区断点/范围。我正在使用一个小函数为我的查询提供合适的日期断点,这样我就不必不断更新我的所有视图

但由于在查询中使用了该函数,分区被忽略了。我是否别无选择,只能将硬编码的值放在查询中的任何地方并不断修改它们

这是一个重现问题的示例

更新:根据标记的答案更改下面的
PartitionDate
函数后,在短时间内一切正常(发生分区消除)。然后,查询又开始变得糟糕。当我运行由date函数过滤的简单查询时,分区不再被消除

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

一种解决方法是首先将函数结果分配给变量

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的改进之处,但我目前还不能对此进行测试。一种解决方法是首先将函数结果分配给变量

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的改进之处,但我目前无法对此进行测试

您能告诉我们select dbo.PartitionQueryDate()返回什么吗。我打赌它不会返回您认为它会返回的内容。
FK\u Order\u Customer
在使用分区引用或不使用分区引用时必须使用相同的方式。无法使用
OrderDate
对索引进行分区,因为它没有(也不包括)该列。@benjaminmoskovits,PartitionQueryDate()在脚本中。@DenisRubashkin,很好的捕获,脚本已更新,与问题无关。我原以为索引在创建时会失败。+1为了提供一个完整的可运行样本,您能告诉我们select dbo.PartitionQueryDate()返回什么吗。我打赌它不会返回您认为它会返回的内容。
FK\u Order\u Customer
在使用分区引用或不使用分区引用时必须使用相同的方式。无法使用
OrderDate
对索引进行分区,因为它没有(也不包括)该列。@benjaminmoskovits,PartitionQueryDate()在脚本中。@DenisRubashkin,很好的捕获,脚本已更新,与问题无关。我原以为索引在创建时会失败。+1用于提供完整的可运行样本,两个选项中的任何一个都有效。事后看来,似乎我真的应该考虑尝试一些这样的变化,但我没有。这两种选择都有效。事后看来,似乎我真的应该尝试一些这样的变化,但我没有。