Estou tentando aprender particionamento de tabela. No entanto, estou lutando para entender por que o SQL Server está se comportando para uma consulta simples.
Conjunto de dados de teste
/* --------------------------------------------------
-- Create helper function GetNums by Itzik Ben-Gan
-- http://sqlmag.com/sql-server/virtual-auxiliary-table-numbers
-- GetNums is used to insert test data
-------------------------------------------------- */
-- Drop helper function if it already exists
IF OBJECT_ID('GetNums') IS NOT NULL
DROP FUNCTION GetNums;
GO
-- Create helper function
CREATE FUNCTION GetNums(@n AS BIGINT) RETURNS TABLE AS RETURN
WITH
L0 AS(SELECT 1 AS c UNION ALL SELECT 1),
L1 AS(SELECT 1 AS c FROM L0 AS A CROSS JOIN L0 AS B),
L2 AS(SELECT 1 AS c FROM L1 AS A CROSS JOIN L1 AS B),
L3 AS(SELECT 1 AS c FROM L2 AS A CROSS JOIN L2 AS B),
L4 AS(SELECT 1 AS c FROM L3 AS A CROSS JOIN L3 AS B),
L5 AS(SELECT 1 AS c FROM L4 AS A CROSS JOIN L4 AS B),
Nums AS(SELECT ROW_NUMBER() OVER(ORDER BY (SELECT NULL)) AS n FROM L5)
SELECT TOP (@n) n FROM Nums ORDER BY n;
GO
/* ------------------------------------------------------------
-- Create example Partitioned Table (Heap)
-- The Partition Column is a DATE column
-- The Partition Function is RANGE RIGHT
-- The Partition Scheme maps all partitions to [PRIMARY]
------------------------------------------------------------ */
-- Drop objects if they already exist
IF EXISTS (SELECT * FROM sys.tables WHERE name = N'Sales')
DROP TABLE Sales;
IF EXISTS (SELECT * FROM sys.partition_schemes WHERE name = N'psSales')
DROP PARTITION SCHEME psSales;
IF EXISTS (SELECT * FROM sys.partition_functions WHERE name = N'pfSales')
DROP PARTITION FUNCTION pfSales;
-- Create the Partition Function
CREATE PARTITION FUNCTION pfSales (DATE)
AS RANGE right FOR VALUES
('2013-01-01', '2014-01-01', '2015-01-01');
-- Create the Partition Scheme
CREATE PARTITION SCHEME psSales
AS PARTITION pfSales
ALL TO ([Primary]);
-- Create the Partitioned Table (Heap) on the Partition Scheme
CREATE TABLE Sales
(
SalesDate DATE constraint ck_date check(SalesDate<'2016-01-01'),
Quantity INT
) ON psSales(SalesDate);
-- Insert test data
INSERT INTO Sales(SalesDate, Quantity)
SELECT DATEADD(DAY,dates.n-1,'2012-01-01') AS SalesDate, qty.n AS Quantity
FROM GetNums(DATEDIFF(DD,'2012-01-01','2016-01-01')) dates
CROSS JOIN GetNums(1000) AS qty;
Consulta
select count(1) from sales where SalesDate>'20160101'
Consulte o plano de execução abaixo.
Perguntas
- Por que SQL fazendo CONVERT_IMPLICIT
- Por que o SQL não está fazendo a detecção de contradição para evitar a verificação da tabela.
Muito Obrigado
Você está obtendo um plano parametrizado trivial e simples para sua consulta simples.
Adicione
AND 1 = (SELECT 1);
ao final de sua consulta e você obterá a detecção constante de varredura/contradição.Usar apenas
AND 1 = 1
nem sempre funciona se o objetivo é também evitar planos triviais. Veja Planos de Consulta: Otimização Trivial vs Parametrização Simples por Erik Darling.Você também deve adquirir o hábito de ser cuidadoso com os tipos de dados. Uma string não é uma data e não há sintaxe T-SQL especial para especificar um literal de data. Você pode usar
CONVERT
para ser explícito, por exemploSalesDate > CONVERT(date, '20160101', 112)
.Leitura relacionada: Por que a eliminação de partições não funciona? por Paulo Branco.
Porque você tem um literal na consulta que precisa ser analisado e convertido em uma data. Esta não é uma preocupação de desempenho.
Sem índices, uma verificação de tabela é inevitável. No entanto, como você pode ver nas propriedades do operador de varredura de tabela, uma busca é usada para que apenas a partição que contém o
SalesDate
valor especificado seja varrida. Execute a consulta comSTATISTICS IO ON
e sem aWHERE
cláusula para ver o impacto da eliminação da partição:A operação de busca com reconhecimento de partição foi introduzida no SQL Server 2008 . Anteriormente (SQL 2005), a eliminação de partição era realizada com operadores de plano de execução separados.
EDIT Acabei de perceber que a questão principal era principalmente sobre a restrição de verificação do que os limites da partição. Acho que essa resposta ainda fornece algum valor, então não a excluirei.