Deparo-me com esta questão algumas vezes, por isso acho que é daquelas que merece uma entrada aqui.
Já criei esta demo há algum tempo para mostrar a um colega de trabalho o que acontece quando ajudamos o query optimizer, dizendo-lhe algumas coisas que nós já sabemos sobre os nossos dados.
Neste caso concreto, “particionar” tabelas manualmente, mas sem colocar nenhuma check constraint serve para… pouco. 🙂
Sim, podemos ter as partições em outros filegroups e em diferentes discos, mas em termos de performance é muito melhor ajudar o motor do SGBD (neste caso o meu SQL Server) o mais que pudermos.
E há algo simples que podemos fazer para ajudar.
Vejamos um caso simples
Criamos umas tabelas
CREATE TABLE [dbo].[Dates2015](
[id] [bigint] primary key IDENTITY(1,1) NOT NULL,
[Dt_ref] [date] NOT NULL
) ON [PRIMARY]
GO
CREATE TABLE [dbo].[Dates2016](
[id] [bigint] primary key IDENTITY(1,1) NOT NULL,
[Dt_ref] [date] NOT NULL
) ON [PRIMARY]
GO
CREATE TABLE [dbo].[Dates2017](
[id] [bigint] primary key IDENTITY(1,1) NOT NULL,
[Dt_ref] [date] NOT NULL
) ON [PRIMARY]
GO
CREATE TABLE [dbo].[Dates2018](
[id] [bigint] primary key IDENTITY(1,1) NOT NULL,
[Dt_ref] [date] NOT NULL
) ON [PRIMARY]
GO
e uma vista apenas a juntar as 4
CREATE VIEW [dbo].[DatesAll]
AS
SELECT *
FROM
dbo.Dates2015
union all
SELECT *
from
dbo.Dates2016
union all
SELECT *
from
dbo.Dates2017
union all
SELECT *
from
dbo.Dates2018
GO
Vamos ligar o nosso “Actual Execution Plan” e ver o que acontece.
select top 1000 *
from [dbo].[DatesAll]

É justo… temos as tabelas vazias, mas como temos sempre um estimated rows de 1, vamos lá “tocar” e ver que não há nada.
Esta query também não deve ter truque…
select top 100 *
from [dbo].[DatesAll]
where dt_ref < '2015-01-06'

Vamos lá a ver se podemos ajudar aqui um pouco o nosso “amigo” SQL Server.
Como “sabemos” que dentro de cada tabela só vamos ter datas do ano correspondente, criamos umas check constraints
alter table [dbo].[Dates2015]
add constraint dt_2015
check ( dt_ref >= '2015-01-01'
and
dt_ref <= '2015-12-31' )
alter table [dbo].[Dates2016]
add constraint dt_2016
check ( dt_ref >= '2016-01-01'
and
dt_ref <= '2016-12-31' )
alter table [dbo].[Dates2017]
add constraint dt_2017
check ( dt_ref >= '2017-01-01'
and
dt_ref <= '2017-12-31' )
alter table [dbo].[Dates2018]
add constraint dt_2018
check ( dt_ref >= '2018-01-01'
and
dt_ref <= '2018-12-31' )
E agora?
select top 100 *
from [dbo].[DatesAll]
where dt_ref < '2015-01-06'

Agora o SQL Server “sabe” que a data só poderá estar numa das 4 tabelas da vista. E nem toca nas outras.
Não dói nada, pois não?