Clausula TOP em Subqueries

Clausula TOP em Subqueries

Tempo de leitura: 2 minutos

Ola Galera! Vou postar uma coisa que hoje estava avaliando junto a um amigo desenvolvedor aqui na nossa fábrica. Marcos Meskelis…Um dos melhores que ja conheci…dono de uma super lógica. Já me ajudou a sair de várias, mas, vamos aos fatos e ao SQL Server (a melhor parte). Tinhamos uma query que criava uma derived table e que dentro dela havia duas outras quries simples…por um tempo que conversavamos sobre o “Brasileirão” e tal… Veio a pergunta! O que o SQL Server faz se dentro da subquery uma das consultas tiver uma clausula TOP e a consulta “externa” que gera a Derived Table também tiver uma Clausula TOP que retorna uma menor quantidade de linhas da Clausula TOP interna? Será que o SQL Server irá ler as duas tabelas da subquery pra aplicar o filtro no TOP da query externa no output das  subqueries? A melhor resposta que tivemos de imediato foi. Vamos Testar!  Crio duas tabelas uma de cliente e uma outra tabela de fornecedor. Na tabela TB_CLIENTE e na tabela TB_FORNECEDOR e realizo a inserção de seis registros para cada.

use tempdb
go
IF OBJECT_ID(‘dbo.TB_CLIENTE’) IS NOT NULL
DROP TABLE dbo.TB_CLIENTE ;
IF OBJECT_ID(‘dbo.TB_FORNECEDOR’) IS NOT NULL
DROP TABLE dbo.TB_FORNECEDOR ;

CREATE TABLE dbo.TB_CLIENTE
(
COD INT IDENTITY
,NOME VARCHAR(50)
,CPF CHAR(20)
,RG CHAR(25)
CONSTRAINT PK_TB_CLIENTE PRIMARY KEY CLUSTERED(COD)
)

CREATE TABLE dbo.TB_FORNECEDOR
(
COD INT IDENTITY
,RAZAO_SOCIAL VARCHAR(50)
,NOME_FANTASIA VARCHAR(80)
,CNPJ CHAR(20)
CONSTRAINT PK_TB_FORNECEDOR PRIMARY KEY CLUSTERED(COD)
)

INSERT INTO dbo.TB_CLIENTE(NOME,CPF,RG) 
VALUES (‘THIAGO ALENCAR’,’89636978925′,’78452362X’) 
,(‘EMANOEL ALENCAR’,’79636978925′,’88452362X’) 
,(‘CAIO LACRAIA’,’99636978925′,’784523625′) ;

INSERT INTO dbo.TB_CLIENTE(NOME,CPF,RG) 
VALUES (‘ALENCAR’,’89636978925′,’78452362X’) 
,(‘EMANOEL ‘,’79636978925′,’88452362X’) 
,(‘CAIO ‘,’99636978925′,’784523625’) ;
INSERT INTO dbo.TB_FORNECEDOR(RAZAO_SOCIAL,NOME_FANTASIA,CNPJ)
VALUES (‘D2 DA SILVA’,’MISIFIO LTDA’,’01.222.333/0001-12′)
,(‘KARATE / ARTES ‘,’JULIAO LTDA’,’01.222.333/0001-00′)
,(‘T. BUENO LTDA’,’TB GUARULHOS’,’01.222.333/0001-00′)
INSERT INTO dbo.TB_FORNECEDOR(RAZAO_SOCIAL,NOME_FANTASIA,CNPJ)
VALUES (‘D2′,’MISIFIO LTDA’,’01.222.333/0001-12′)
,(‘ARTES ‘,’JULIAO LTDA’,’01.222.333/0001-00′)
,(‘T. BUENO LTDA’,’GUARULHOS’,’01.222.333/0001-00′)

Vamos testar…rs! Habilite o plano de execução (Ctrl+M) e execute a query abaixo:

SET STATISTICS PROFILE ON
SELECT 
TOP 6 * 
FROM 
(
SELECT  COD, NOME,CPF FROM dbo.TB_CLIENTE 
UNION ALL
SELECT COD, NOME_FANTASIA,CNPJ FROM DBO.TB_FORNECEDOR 
) AS A
OPTION(RECOMPILE)
SET STATISTICS PROFILE OFF
A tabela de TB_CLIENTE contém 6 registros, assim como a de fornecedor. O SQL Server realiza um clustered index scan nas duas tabelas, porém, não é retornado nenhum registro da tabela de fornecedor. Pois o SQL Server  sabe que existem 6 registros na tabela de cliente e o TOP da consulta “externa” solicita o retorno de 6 registros.  Esse comportamento pode ser visto no plano de execução.
Obs: O SQL Server é completamente inteligente para não realizar a leitura em outro indice de uma  outra tabela. Já que o resultado do TOP quer apenas 6 registros. Vale lembrar que esse é apenas  um cenário para ver como as coisas funionam e qual caminho o SQL Server optou usar. Quando o TOP  é maior que 100 o SQL Server realiza um outro algoritmo. Isso pode mudar o plano de execução
 apresentado aqui.

 

Deixe uma resposta

%d blogueiros gostam disto: