Inquiridor
Dúvidas quanto ao Plano de execução

Pergunta
-
Boa tarde pessoal,
Eu estou rodando uma proc meio chatinha, notei uma lentidão acima do normal, bem, olhei o plano de execução e vi um table scan e um clustered index scan. Esses dois eu ja acertei, só tenho index seek agora.
Ok, mas algumas coisas aparecem no plano e eu não sei o que é:
Table Spool (Eager Spool) cost 30%
Hash Match (Inner Join) cost 15%
Nesta proc eu faço algumas inserções em tabelas temporárias, faço alguns joins tb.
Outra coisa tenho um :
Clustered Index Seek cost 40%
Isso é normal ?
Todas as Respostas
-
Olá Rick,
Uma pergunta, no seu WHERE, está utilizando algum "OR" ou "IN"?
Em algumas situações é interessante fazer um UNION de duas consultas do que usar OR.
Exemplo que pode ter mau desempenho:
SELECT NomeProduto FROM Produtos WHERE TipoProduto = 45 OR TipoProduto = 68
Outra forma de obter o mesmo resultado mas pode obter melhor desempenho:
SELECT NomeProduto FROM Produtos WHERE TipoProduto = 45
UNION ALL
SELECT NomeProduto FROM Produtos WHERE TipoProduto = 68
Tente postar aqui pelo menos parte do seu código para termos analisar melhor.
Abraço
-
Não tenho numu "or" ou "in"
Bom, o código é meio chatinho e possívelmente não é o ideal não fui eu quem o fez.
Basicamente ele gera duas tabelas temporárias para emissão de relatório usando crystal.
a parte de código que eu fiz é apenas os create index e drop index em uma das temporárias.
Declare
@tabela as char(25)Declare
@instrucao as varchar(1500)Declare
@ordem as varchar(200)-- Atribui o nome para a tabela temporaria
Select
@tabela = '_AVLVLR_' + replace(replace(replace(replace(Convert(varchar(40),getdate(),121),'-',''),':',''),' ',''),'.','')-- Criação da tabela temporaria que servirá de base para o relatorio
Select
-- Campos Chavesa
.projeto_codigo,a
.subprojeto_codigo,a
.equipamento_codigo,a
.avaliacao_codigo, -- Campos do Cabeçalhod
.cliente_razao_social as Razao_Social,c
.subprojeto_data_base as Data_Base,c
.subprojeto_descricao as Unidade, -- Campos do Detalhe Convert(Varchar(30), AME.dbo.FU_AVL_concatena(' / ',ltrim(rtrim(isnull(a.avaliacao_patrimonio,''))), ltrim(rtrim(isnull(a.avaliacao_incorp,''))))) as num_bem,a
.avaliacao_ficha as ficha,a
.avaliacao_equipamento_descricao as Descricao_Bem,a
.equipamento_cotacao_data, Convert(numeric(6,2),null) as vida_util, Convert(numeric(6,2),null) as vida_util_perc, Convert(numeric(18,2),null) as valor_reposicao, Convert(numeric(18,2),null) as valor_mercado, Convert(numeric(18,2),null) as valor_maximo_seguravel, Convert(numeric(18,2),null) as valor_danos_eletricos,a
.localidade_equipamento_codigo as localidade_equipamento_codigo, Convert(varchar(25), Null) as localidade_equipamento_sigla, Convert(varchar(100), Null) as localidade_equipamento_descricao,a
.planta_seguro_codigo as planta_seguro_codigo, Convert(varchar(15), Null) as planta_seguro_numero, Convert(varchar(100), Null) as planta_seguro_descricao,a
.centro_custo_codigo as centro_custo_codigo, Convert(varchar(15), Null) as centro_custo_numero, Convert(varchar(100), Null) as centro_custo_descricao,a
.conta_contabil_codigo as conta_contabil_codigo, Convert(varchar(15), Null) as conta_contabil_conta, Convert(varchar(100), Null) as conta_contabil_descricao,a
.avaliacao_nota,a
.avaliacao_ano_aparente,a
.avaliacao_quantidade, Convert(tinyint, Null) as meio_codigo, Convert(char(2), Null) as meio_sigla, Convert(smallint, Null) as classe_codigo, Convert(char(3), Null) as classe_sigla, Convert(numeric(5,2), Null) as classe_danos_eletricos,c
.subprojeto_descricao,a
.segmento_siglaInto
#rel_avaliacao_analitico
From
avaliacao a
,projeto b
,subprojeto c
,cliente d
,equipamento_cotacao f
Where
a
.projeto_codigo = 1262 ANDa
.subprojeto_codigo = 1 ANDb
.projeto_codigo = a.projeto_codigo ANDc
.projeto_codigo = a.projeto_codigo ANDc
.subprojeto_codigo = a.subprojeto_codigo ANDd
.cliente_codigo = b.cliente_codigo ANDf
.equipamento_codigo = a.equipamento_codigo ANDf
.projeto_codigo=1262 ANDf
.subprojeto_codigo=1-- Identifica os campos com as tabelas correspondentes
-- Conta_contabil, Centro_Custo, Planta_seguro e Localidade_equipamento
CREATE
clustered INDEX tmprel001 on #rel_avaliacao_analitico (projeto_codigo asc,subprojeto_codigo asc,localidade_equipamento_codigo asc)Update
#rel_avaliacao_analiticoSet
localidade_equipamento_sigla = b.localidade_equipamento_sigla,localidade_equipamento_descricao
= b.localidade_equipamento_descricaoFrom
#rel_avaliacao_analitico a,localidade_equipamento b
Where
a.projeto_codigo = b.projeto_codigo ANDa
.subprojeto_codigo = b.subprojeto_codigo ANDa
.localidade_equipamento_codigo = b.localidade_equipamento_codigodrop
INDEX #rel_avaliacao_analitico.tmprel001CREATE
clustered INDEX tmprel001 on #rel_avaliacao_analitico (projeto_codigo asc,subprojeto_codigo asc,planta_seguro_codigo asc)Update
#rel_avaliacao_analiticoSet
planta_seguro_numero = b.planta_seguro_numero,planta_seguro_descricao
= b.planta_seguro_descricaoFrom
#rel_avaliacao_analitico a,planta_seguro b
Where
a.projeto_codigo = b.projeto_codigo ANDa
.subprojeto_codigo = b.subprojeto_codigo ANDa
.planta_seguro_codigo = b.planta_seguro_codigodrop
INDEX #rel_avaliacao_analitico.tmprel001CREATE
clustered INDEX tmprel001 on #rel_avaliacao_analitico (projeto_codigo asc,subprojeto_codigo asc,centro_custo_codigo asc)Update
#rel_avaliacao_analiticoSet
centro_custo_numero = b.centro_custo_numero,centro_custo_descricao
= b.centro_custo_descricaoFrom
#rel_avaliacao_analitico a,centro_custo b
Where
a.projeto_codigo = b.projeto_codigo ANDa
.subprojeto_codigo = b.subprojeto_codigo ANDa
.centro_custo_codigo = b.centro_custo_codigodrop
INDEX #rel_avaliacao_analitico.tmprel001CREATE
clustered INDEX tmprel001 on #rel_avaliacao_analitico (projeto_codigo asc,subprojeto_codigo asc,conta_contabil_codigo asc)Update
#rel_avaliacao_analiticoSet
conta_contabil_conta = b.conta_contabil_conta,conta_contabil_descricao
= b.conta_contabil_descricaoFrom
#rel_avaliacao_analitico a,conta_contabil b
Where
a.projeto_codigo = b.projeto_codigo ANDa
.subprojeto_codigo = b.subprojeto_codigo ANDa
.conta_contabil_codigo = b.conta_contabil_codigodrop
INDEX #rel_avaliacao_analitico.tmprel001-- Cria a tabela para receber os calculos
Execute
dbo.SP_AVL_avaliacao_criatmp @tabela-- Coloca os dados necessarios para calculos na temporária
Select
@instrucao = ' Insert ' + @tabela + ' (projeto_codigo,
subprojeto_codigo,
equipamento_codigo,
avaliacao_codigo,
equipamento_cotacao_data,
avaliacao_nota,
avaliacao_ano_aparente,
avaliacao_quantidade )
Select projeto_codigo,
subprojeto_codigo,
equipamento_codigo,
avaliacao_codigo,
equipamento_cotacao_data,
avaliacao_nota,
avaliacao_ano_aparente,
avaliacao_quantidade
From avaliacao
where projeto_codigo = '
+ convert(char(4),1262) + 'andsubprojeto_codigo = '
+ convert(char(4),1)Execute
(@instrucao)-- Calcula os valores da tabela temporária
Execute
dbo.SP_AVL_Avaliacao_Valores @tabela-- Realiza Update na tabela do relatório com os valores calculados
CREATE
clustered INDEX tmprel001 on #rel_avaliacao_analitico (projeto_codigo asc,equipamento_codigo asc,subprojeto_codigo asc)Select
@instrucao = ' Update #rel_avaliacao_analiticoSet meio_codigo = b.meio_codigo,
classe_codigo = b.classe_codigo,
classe_danos_eletricos = b.danos_eletricos,
vida_util = b.vida_util,
vida_util_perc = b.vida_util_perc,
valor_reposicao = b.valor_reposicao,
valor_mercado = b.valor_mercado,
valor_maximo_seguravel = b.valor_maximo_seguravel,
valor_danos_eletricos = b.valor_danos_eletricos
From #rel_avaliacao_analitico a, '
+ @tabela + ' b' + ' Where a.avaliacao_codigo = b.avaliacao_codigo anda.projeto_codigo = b.projeto_codigo and
a.equipamento_codigo = b.equipamento_codigo and
a.subprojeto_codigo = b.subprojeto_codigo '
Execute
(@instrucao)drop
INDEX #rel_avaliacao_analitico.tmprel001-- Apaga a tabela temporária de calculos , fiscamente do banco
Select
@instrucao = 'Drop table ' + @tabelaExecute
(@Instrucao)-- Acerta as siglas do MEIO e da Classe
CREATE
clustered INDEX tmprel001 on #rel_avaliacao_analitico (meio_codigo asc)Update
#rel_avaliacao_analiticoSet
meio_sigla = b.meio_siglaFrom
#rel_avaliacao_analitico a,meio b
Where
a.meio_codigo = b.meio_codigodrop
INDEX #rel_avaliacao_analitico.tmprel001CREATE
clustered INDEX tmprel001 on #rel_avaliacao_analitico (classe_codigo asc)Update
#rel_avaliacao_analiticoSet
classe_sigla = b.classe_siglaFrom
#rel_avaliacao_analitico a,classe b
Where
a.classe_codigo = b.classe_codigodrop
INDEX #rel_avaliacao_analitico.tmprel001-- Acerta a ordem de saída da infromação
CREATE
CLUSTERED INDEX tmprel on #rel_avaliacao_analitico (Projeto_Codigo,SubProjeto_Codigo,segmento_sigla)If
1 = 1Begin
CREATE INDEX tmprel2 on #rel_avaliacao_analitico (descricao_bem ASC, valor_reposicao DESC) Select @ordem = 'Order by descricao_bem ASC , valor_reposicao DESC 'End
Else
If 1 = 2Begin
CREATE INDEX tmprel on #rel_avaliacao_analitico (valor_reposicao DESC, descricao_bem ASC) Select @ordem = 'Order by valor_reposicao DESC, descricao_bem ASC'End
Set
nocount off-- Seleciona os campos para o Crystal Reports
Select
@instrucao = 'Select r.projeto_codigo,
Convert(char(3),replicate(''0'', 3 - Len(r.subprojeto_codigo)) + Convert(varchar(3), r.subprojeto_codigo)) as subprojeto_codigo,
subprojeto_descricao,
equipamento_codigo,
avaliacao_codigo,
Razao_Social,
Data_Base,
Unidade,
num_bem,
ficha,
Descricao_Bem,
equipamento_cotacao_data,
vida_util,
vida_util_perc,
valor_reposicao,
valor_mercado,
valor_maximo_seguravel,
valor_danos_eletricos,
localidade_equipamento_codigo,
localidade_equipamento_sigla,
localidade_equipamento_descricao,
planta_seguro_codigo,
planta_seguro_numero,
planta_seguro_descricao,
centro_custo_codigo,
centro_custo_numero,
centro_custo_descricao,
conta_contabil_codigo,
conta_contabil_conta,
conta_contabil_descricao,
avaliacao_nota,
avaliacao_ano_aparente,
avaliacao_quantidade,
meio_codigo,
meio_sigla,
classe_codigo,
classe_sigla,
classe_danos_eletricos,
r.segmento_sigla,
s.segmento_acessorio,
s.segmento_montagem,
s.segmento_admengproj
--Into lixo5
From
#rel_avaliacao_analitico r inner join segmentos s on r.Projeto_Codigo=s.Projeto_Codigo
and r.subprojeto_codigo=s.SubProjeto_Codigo
and r.segmento_sigla=s.segmento_sigla '
+
@ordemExecute
(@instrucao) -
Rick,
Vendo o código, realmente está um tanto complicado de analisar qual o possível problema. O código deveria estar rápido para execução. O que pode estar fazendo com que demore é a quantidade de dados.
Quanto de daos você tem hoje??
Abraço
-
50.000 registro, até não é muito.
Alguns problemas que eu sei que não vai ter como acertar é que por exemplo o relatório retorna TODOS os registro (50mil), mas até aí tudo bem, o problema está sendo 50% de processamento. Sem contar que este script chama outro script que faz zilhões de update em tabelas temporárias (como eu disse não fui eu que fiz hehehe).
Bom vamos ao que pode me dar uma luz no fim do túnel:
Que diabos é esse negócio de Table Spooling ?
E esse tal de Hash Join ?
E o fato do meu clustered index estar comendo 40% do meu processamento, é normal, pode ocorrer?
Se você tiver algum link pra eu ler sobre esses trecos aí fico grato, pois além desses queria dar uma lida sobre os bookmarks, embora estejam comendo 0% do meu processamento.
vlws.
-
Rick,
Nesse link tem algumas informações bem interessantes sobre o plano de execução:
http://www.sql-server-performance.com/query_execution_plan_analysis.asp
Sobre o Table Spool, ele ocorre quando o SQL tem que fazer a criação de uma área temporária dentro da TEMPDB para trabalhar com os dados. Para resolver isso, em geral teria que verificar a possibilidade de modificar a consulta, mas, tente analizar ela dentro do Index Tuning Wizard (Se for sql 2000) ou no Database Tuning Advisor (SQL 2005), pode ser que recomende algum índice para melhorar o desempenho.
Abraço
-
Bom dia Rick
Um outro problema que vejo é a criação dos índices nas tabelas temporárias, o SQL Server gasta tempo criando, mantendo e excluíndo o índice, não seria mais interessante incluir os dados baseados em um ORDER BY ? Creio que sim, acho que com essa simples alteração você pode ganhar um tempo precioso.
Espero ter ajudado
-
@Alexandre,
Obrigado pelo link , quanto ao uso do tunning, ja tentei usar, o problema mesmo está na criação e updates em tabelas temporárias, vou tentar refazer a rotina sem usar temporárias.
@Anderson,
A inclusão de indices na temporária foi uma tentativa de melhora em zilhões de inserts e updates, note que essa rotina chama uma outra que também tem zilhões de updates, ta osso isso.
Como disse acima, vou tentar refazer a rotina sem usar temporárias.
-
segue alguumas instrucoes que foram a recompilacao.
comandos set dentro de proc
criacao de tabelas temporarias
execucao usando exec ('' )
criacao de objetos de banco como indices, etc.
se sua proc tem algum desses procedimentos era sera recompilada todas as vezes que for executada.
Abs
-
Marcelo,
Eu mudei algumas coisas, mas não consegui fugir da criação de tabelas temporárias.
Quanto a instruções "set" eu posso substituir por "select", seria melhor ou da na mesma ?
Quanto a criação de indices posso remover pra ver como fica.
Eu basicamente mudei um pouco o primeiro select, que estava usando "tabela1,tabela2,tabela3" que pelo que sei não é mais suportado no SQL 2005, com isto consegui retirar 4 updates que ocorriam no meio da proc, então faço o select dos dados que preciso (acho que isto deve melhorar o desempenho)
Segue como está a proc:
Note que esta proc executa outras duas, uma apenas cria uma tabela (não temporária), a outra faz uma série de updates nesta tabela que foi criada.
Code SnippetDeclare
@tabela as char(25)Declare
@instrucao as varchar(1500)Declare
@ordem as varchar(200)-- Atribui o nome para a tabela temporaria
Select
@tabela = '_AVLVLR_' + replace(replace(replace(replace(Convert(varchar(40),getdate(),121),'-',''),':',''),' ',''),'.','')-- Criação da tabela temporaria que servirá de base para o relatorio
Select
-- Campos Chavesa
.projeto_codigo,a
.subprojeto_codigo,a
.equipamento_codigo,a
.avaliacao_codigo, -- Campos do Cabeçalhod
.cliente_razao_social as Razao_Social,c
.subprojeto_data_base as Data_Base,c
.subprojeto_descricao as Unidade, -- Campos do Detalhe Convert(Varchar(30), AME.dbo.FU_AVL_concatena(' / ',ltrim(rtrim(isnull(a.avaliacao_patrimonio,''))), ltrim(rtrim(isnull(a.avaliacao_incorp,''))))) as num_bem,a
.avaliacao_ficha as ficha,a
.avaliacao_equipamento_descricao as Descricao_Bem,a
.equipamento_cotacao_data, Convert(numeric(6,2),null) as vida_util, Convert(numeric(6,2),null) as vida_util_perc, Convert(numeric(18,2),null) as valor_reposicao, Convert(numeric(18,2),null) as valor_mercado, Convert(numeric(18,2),null) as valor_maximo_seguravel, Convert(numeric(18,2),null) as valor_danos_eletricos,a
.localidade_equipamento_codigo as localidade_equipamento_codigo,g
.localidade_equipamento_sigla as localidade_equipamento_sigla,g
.localidade_equipamento_descricao as localidade_equipamento_descricao,a
.planta_seguro_codigo as planta_seguro_codigo,h
.planta_seguro_numero as planta_seguro_numero,h
.planta_seguro_descricao as planta_seguro_descricao,a
.centro_custo_codigo as centro_custo_codigo,i
.centro_custo_numero as centro_custo_numero,i
.centro_custo_descricao as centro_custo_descricao,a
.conta_contabil_codigo as conta_contabil_codigo,j
.conta_contabil_conta as conta_contabil_conta,j
.conta_contabil_descricao as conta_contabil_descricao,a
.avaliacao_nota,a
.avaliacao_ano_aparente,a
.avaliacao_quantidade, Convert(tinyint, Null) as meio_codigo, Convert(char(2), Null) as meio_sigla, Convert(smallint, Null) as classe_codigo, Convert(char(3), Null) as classe_sigla, Convert(numeric(5,2), Null) as classe_danos_eletricos,c
.subprojeto_descricao,a
.segmento_sigla,s
.segmento_acessorio,s
.segmento_montagem,s
.segmento_admengprojInto
#rel_avaliacao_analitico
From
((((((((avaliacao a inner join projeto b on b.projeto_codigo = a.projeto_codigo) inner join subprojeto c on c.projeto_codigo = a.projeto_codigo and c.subprojeto_codigo = a.subprojeto_codigo) inner join cliente d on d.cliente_codigo = b.cliente_codigo) inner join equipamento_cotacao f on f.equipamento_codigo = a.equipamento_codigo) inner join localidade_equipamento g on g.localidade_equipamento_codigo = a.localidade_equipamento_codigo) left outer join planta_seguro h on (h.planta_seguro_codigo=a.planta_seguro_codigo and h.projeto_codigo=a.projeto_codigo and h.subprojeto_codigo=a.subprojeto_codigo)) inner join centro_custo i on i.centro_custo_codigo = a.centro_custo_codigo) inner join conta_contabil j on j.conta_contabil_codigo = a.conta_contabil_codigo) inner join segmentos s on s.segmento_sigla=a.segmento_siglaWhere
( a.projeto_codigo = @projeto_codigo and a.subprojeto_codigo = @subprojeto_codigo) AND ( b.projeto_codigo = @projeto_codigo) AND ( c.projeto_codigo = @projeto_codigo and c.subprojeto_codigo = @subprojeto_codigo) AND ( f.projeto_codigo = @projeto_codigo and f.subprojeto_codigo = @subprojeto_codigo) AND ( g.projeto_codigo = @projeto_codigo and g.subprojeto_codigo = @subprojeto_codigo) AND ( i.projeto_codigo = @projeto_codigo and i.subprojeto_codigo = @subprojeto_codigo) AND ( j.projeto_codigo = @projeto_codigo and j.subprojeto_codigo = @subprojeto_codigo) AND ( s.projeto_codigo = @projeto_codigo and s.subprojeto_codigo = @subprojeto_codigo)-- Cria a tabela para receber os calculos
Execute
dbo.SP_AVL_avaliacao_criatmp @tabela-- Coloca os dados necessarios para calculos na temporária
Select
@instrucao = ' Insert ' + @tabela + ' (projeto_codigo,
subprojeto_codigo,
equipamento_codigo,
avaliacao_codigo,
equipamento_cotacao_data,
avaliacao_nota,
avaliacao_ano_aparente,
avaliacao_quantidade )
Select projeto_codigo,
subprojeto_codigo,
equipamento_codigo,
avaliacao_codigo,
equipamento_cotacao_data,
avaliacao_nota,
avaliacao_ano_aparente,
avaliacao_quantidade
From avaliacao
where projeto_codigo = '
+ convert(char(4),@projeto_codigo) + 'andsubprojeto_codigo = '
+ convert(char(4),@subprojeto_codigo)Execute
(@instrucao)-- Calcula os valores da tabela temporária
Execute
dbo.SP_AVL_Avaliacao_Valores @tabela-- Realiza Update na tabela do relatório com os valores calculados
CREATE
clustered INDEX tmprel001 on #rel_avaliacao_analitico (projeto_codigo asc,equipamento_codigo asc,subprojeto_codigo asc)Select
@instrucao = ' Update #rel_avaliacao_analiticoSet meio_codigo = b.meio_codigo,
classe_codigo = b.classe_codigo,
classe_danos_eletricos = b.danos_eletricos,
vida_util = b.vida_util,
vida_util_perc = b.vida_util_perc,
valor_reposicao = b.valor_reposicao,
valor_mercado = b.valor_mercado,
valor_maximo_seguravel = b.valor_maximo_seguravel,
valor_danos_eletricos = b.valor_danos_eletricos
From #rel_avaliacao_analitico a, '
+ @tabela + ' b' + ' Where a.avaliacao_codigo = b.avaliacao_codigo anda.projeto_codigo = b.projeto_codigo and
a.equipamento_codigo = b.equipamento_codigo and
a.subprojeto_codigo = b.subprojeto_codigo '
Execute
(@instrucao)drop
INDEX #rel_avaliacao_analitico.tmprel001-- Apaga a tabela temporária de calculos , fiscamente do banco
Select
@instrucao = 'Drop table ' + @tabelaExecute
(@Instrucao)-- Acerta as siglas do MEIO e da Classe
CREATE
clustered INDEX tmprel001 on #rel_avaliacao_analitico (meio_codigo asc)Update
#rel_avaliacao_analiticoSet
meio_sigla = b.meio_siglaFrom
#rel_avaliacao_analitico a,meio b
Where
a.meio_codigo = b.meio_codigodrop
INDEX #rel_avaliacao_analitico.tmprel001CREATE
clustered INDEX tmprel001 on #rel_avaliacao_analitico (classe_codigo asc)Update
#rel_avaliacao_analiticoSet
classe_sigla = b.classe_siglaFrom
#rel_avaliacao_analitico a,classe b
Where
a.classe_codigo = b.classe_codigodrop
INDEX #rel_avaliacao_analitico.tmprel001-- Acerta a ordem de saída da infromação
If
@ordem_codigo = 1Begin
CREATE INDEX tmprel2 on #rel_avaliacao_analitico (descricao_bem ASC, valor_reposicao DESC) Select @ordem = 'Order by descricao_bem ASC , valor_reposicao DESC 'End
Else
If @ordem_codigo = 2Begin
CREATE INDEX tmprel on #rel_avaliacao_analitico (valor_reposicao DESC, descricao_bem ASC) Select @ordem = 'Order by valor_reposicao DESC, descricao_bem ASC'End
Set
nocount off-- Seleciona os campos para o Crystal Reports
Select
@instrucao = 'Select r.projeto_codigo,
Convert(char(3),replicate(''0'', 3 - Len(r.subprojeto_codigo)) + Convert(varchar(3), r.subprojeto_codigo)) as subprojeto_codigo,
subprojeto_descricao,
equipamento_codigo,
avaliacao_codigo,
Razao_Social,
Data_Base,
Unidade,
num_bem,
ficha,
Descricao_Bem,
equipamento_cotacao_data,
vida_util,
vida_util_perc,
valor_reposicao,
valor_mercado,
valor_maximo_seguravel,
valor_danos_eletricos,
localidade_equipamento_codigo,
localidade_equipamento_sigla,
localidade_equipamento_descricao,
planta_seguro_codigo,
planta_seguro_numero,
planta_seguro_descricao,
centro_custo_codigo,
centro_custo_numero,
centro_custo_descricao,
conta_contabil_codigo,
conta_contabil_conta,
conta_contabil_descricao,
avaliacao_nota,
avaliacao_ano_aparente,
avaliacao_quantidade,
meio_codigo,
meio_sigla,
classe_codigo,
classe_sigla,
classe_danos_eletricos,
segmento_sigla,
segmento_acessorio,
segmento_montagem,
segmento_admengproj
From
#rel_avaliacao_analitico r '
+ @ordemExecute
(@instrucao) -
nas instrucoes concatenadas altere o exec por sp_executesql essa proc mantem planos de execucao, e ao invez de usar tabela temporaria use uma variavel table ( ira recompilar tambem ) mais vc. nao vai perder tempo indo ate o cache procurar a rotina gerada. ( cache miss )
Abs.
-
No caso so sp_executesql, não consegui entender é meio confuso aquilo, por exemplo vi no BOL um exemplo:
Code SnippetDECLARE @IntVariable int;
DECLARE @SQLString nvarchar(500);
DECLARE @ParmDefinition nvarchar(500);
DECLARE @max_title varchar(30);
SET @IntVariable = 197;
SET @SQLString = N'SELECT @max_titleOUT = max(Title)
FROM AdventureWorks.HumanResources.Employee
WHERE ManagerID = @level';
SET @ParmDefinition = N'@level tinyint, @max_titleOUT varchar(30) OUTPUT';
EXECUTE sp_executesql @SQLString, @ParmDefinition, @level = @IntVariable, @max_titleOUT=@max_title OUTPUT;
SELECT @max_title;
Vendo isso fiquei com algumas dúvidas:
- O "N" na frente significa o que?
- na linha onde seta o ParmDefinition, tem umas variáveis, elas estão sendo declaradas ali mesmo ?
- para retoranar por exemplo 20 campos de uma consulta, eu teria que declarar 20 variáveis ali no ParmDefinition ?
O lance sobre usar a variável table ao invés de criar uma tabela tamporária eu não entendi.
-
Rick,
Sobre o sp_executesql, recomendo você dar uma lida nessa matéria:
http://www.sommarskog.se/dyn-search.html
Bem explicado.
Sobre o "N", é usado para identificar dados de caracter Unicode, no caso do NVarchar e NChar.
A declaração de tabelas, você pode usar assim:
DECLARE @NomeDaTabela TABLE (Campo1 INT IDENTITY (1,1), Campo2 VARCHAR (200) )
É melhor que usar o CREATE TABLE #Nome...... Com este, o plano de execução será recompilado, gerando custo de processamento, no caso do DECLARE isso poderá não ocorrer.
Abraço
-
Fiz o lance de usar variavel table, deu certo e tals, mas to com um problema aqui, veja o código:
Minha tabela:
Code SnippetDeclare
@TmpAvaliacao Table (projeto_codigo smallint,sbuprojeto
smallintetc,etc
Erro ocorrem em:
Code SnippetSelect
@instrucao = 'Update ' + @TmpAvaliacao + ' Set meio_codigo = b.meio_codigo,classe_codigo = b.classe_codigo,
classe_danos_eletricos = b.danos_eletricos,
vida_util = b.vida_util,
vida_util_perc = b.vida_util_perc,
valor_reposicao = b.valor_reposicao,
valor_mercado = b.valor_mercado,
valor_maximo_seguravel = b.valor_maximo_seguravel,
valor_danos_eletricos = b.valor_danos_eletricos
From '
+ @TmpAvaliacao + ' a, ' + @tabela + ' b' + ' Where a.avaliacao_codigo = b.avaliacao_codigo anda.projeto_codigo = b.projeto_codigo and
a.equipamento_codigo = b.equipamento_codigo and
a.subprojeto_codigo = b.subprojeto_codigo '
Execute
(@instrucao)Tá dando um erro:
Msg 137, Level 15, State 2, Procedure SP_AVL_REL_avaliacao_conferencia_eletropaulo, Line 276
Must declare the variable '@TmpAvaliacao'.