Eu criei um trabalho SQLAgent e uma das etapas do trabalho executa um procedimento que não está sob meu controle direto. O procedimento contém instruções de impressão e, quando é executado, a saída de todas essas instruções de impressão aparece em Histórico do trabalho->Resumo do arquivo de log->painel de detalhes da linha como uma mensagem. Isso por si só não é um problema, mas essas mensagens ocultam um erro que às vezes pode ocorrer. Como configuro o SQLAgent (ou a etapa de trabalho) de forma que ele ignore essas mensagens (informativas) e mostre apenas mensagens de erro. Etapa para repro: Crie uma etapa de trabalho que tenha a instrução: imprima 'hello world' e execute a etapa de trabalho. O histórico mostra Mensagem executada como usuário: NT SERVICE\SQLAgent$MSSQLSERVER2019. olá mundo [SQLSTATE 01000] (mensagem 0). A etapa deu certo. Agora, se eles são uma série dessas instruções de impressão entre uma instrução SQL cuja execução resulta em um erro de divisão por zero, ela aparecerá como uma mensagem, mas será obscurecida por todas essas saídas de instrução de impressão. Mas se essas mensagens informativas puderem ser suprimidas, a mensagem de erro será facilmente visível.
QFirstLast's questions
Parece haver algo especial sobre 'tR' no agrupamento vietnamita. Appreicate se alguém que sabe sobre isso pode explicar em termos simples. Esse problema foi descoberto durante a instalação do nosso produto em um SQL Server agrupado "vietnamita". Uma das tabelas no esquema tem 'tR' em seu nome, mas um procedimento armazenado está referenciando a tabela em todas as letras minúsculas 'tr'. E esta referência falha.
Acho que essa situação é análoga a '阝' combinando 'ss' em outros agrupamentos.
Aqui está uma reprodução:
select case when 'tr' = 'tR' COLLATE SQL_Latin1_General_CP1_CI_AS then 'match' else 'no match' end
select case when 'tr' = 'tR' COLLATE Vietnamese_CI_AI then 'match' else 'no match' end
select case when 'tr' = 'TR' COLLATE Vietnamese_CI_AI then 'match' else 'no match' end
Resultados:
-----
match
--------
no match
-----
match
O segundo T-SQL produz a incompatibilidade. Outras combinações de 't' e 'R' não.
Estou executando a seguinte consulta no MS SQL Server 2014 (e também no 2014SP3)
SET NOCOUNT ON
CREATE TABLE #GUIDs(
PartyNames_GUID UNIQUEIDENTIFIER NULL,
Party_GUID UNIQUEIDENTIFIER NULL,
FirstName NVARCHAR(255) NULL
)
insert #GUIDs(Party_GUID)
select top 1 Party_GUID
FROM Party a
join PartyNames b on a.Party_ID = b.Party_ID
--Give the optimizer all kinds of choices.
create index i1 on #GUIDs(PartyNames_GUID)
create index i2 on #GUIDs(Party_GUID)
create index i3 on #GUIDs(Party_GUID, PartyNames_GUID)
create index i4 on #GUIDs(PartyNames_GUID,Party_GUID)
update statistics #GUIDs
SELECT PartyNames.PartyNames_ID, PartyNames.LastName, PartyNames.FirstName
FROM Party INNER JOIN PartyNames ON PartyNames.Party_ID = Party.Party_ID
INNER JOIN #GUIDs ON Party.Party_GUID = #GUIDs.Party_GUID --Hard Match on Party_GUID
AND
(#GUIDs.PartyNames_GUID IS NULL OR PartyNames.PartyNames_GUID = #GUIDs.PartyNames_GUID ) --Optional Match
AND
(#GUIDs.FirstName IS NULL OR PartyNames.FirstName = #GUIDs.FirstName ) --Optional Match
drop table #GUIDs
As tabelas Party e PartyNames têm um índice clusterizado em seus _IDs primários, um índice exclusivo não clusterizado em seus respectivos GUIDs e PartyNames tem um índice na chave estrangeira de Party. O DDL para essas tabelas está incluído no final para não confundir a descrição do problema. Party tem cerca de 1,9 milhões de linhas e PartyNames 1,3 milhões. PartyNames pode ter no máximo 3 registros por Party. A consulta acima leva algumas centenas de milissegundos para ser executada. Mas a mesma consulta é executada em 15 ms ou menos no SQL Server 2012, 2016 e 2019. O esquema em todas as versões é o mesmo, exatamente os mesmos dados são BCP e as estatísticas são atualizadas depois que o BCP é feito e antes de executar a consulta. Aqui está a aparência do plano de execução em 2014 E aqui está o plano de execução nas outras versões do SQL Server, 2012, 2016, 2019
Por que 2014 gera um plano tão ruim, que verifica a chave primária do PartyNames em vez de procurar
[PartyNames].[ix_PartyNames_Party_ID? OU melhor, como as versões superiores e inferiores a 2014 conseguem chegar a um bom plano enquanto 2014 não? O plano gerado pelas outras versões é obviamente melhor, pois consome menos CPU e faz menos IOs. É alguma configuração do servidor em 2014 que está causando isso? O custo do otimizador do SQL Server 2014 é muito diferente das versões anteriores ou posteriores? Qualquer ajuda ou ponteiros são apreciados. Eu odiaria pensar que isso é uma falha no SQL Server 2014. E o interessante é que mesmo que o número de registros seja reduzido para alguns milhares, o SQL Server 2014 continua gerando o mesmo plano ruim. Mas remover a última cláusula AND ,(#GUIDs.FirstName IS NULL OR PartyNames.FirstName = #GUIDs.FirstName ) faz com que o SQL Server 2014 gere o mesmo bom plano que as outras versões. Esta é, obviamente, uma reprodução artificial. Os clientes que executam nosso produto no MS SQL Server 2014 reclamaram de desempenho ruim, enquanto os de outras versões não. A solução de problemas leva a essa reprodução simples.
E aqui está o DDL para a geração do esquema
CREATE TABLE [dbo].[Party](
[Party_ID] [int] IDENTITY(1,1) NOT NULL,
[Party_GUID] [uniqueidentifier] ROWGUIDCOL NOT NULL,
CONSTRAINT [pk_Party_Party_ID] PRIMARY KEY CLUSTERED ( [Party_ID] ASC),
CONSTRAINT [uq_Party_Party_GUID] UNIQUE NONCLUSTERED ( [Party_GUID] ASC)
)
GO
ALTER TABLE [dbo].[Party] ADD CONSTRAINT [df_Party_Party_GUID] DEFAULT (newid()) FOR [Party_GUID]
GO
CREATE TABLE [dbo].[PartyNames](
[PartyNames_ID] [int] IDENTITY(1,1) NOT NULL,
[PartyNames_GUID] [uniqueidentifier] ROWGUIDCOL NOT NULL,
[Party_ID] [int] NOT NULL,
[FirstName] [nvarchar](255) NULL,
[MiddleName] [nvarchar](255) NULL,
[LastName] [nvarchar](255) NULL,
CONSTRAINT [pk_PartyNames_PartyNames_ID] PRIMARY KEY CLUSTERED ([PartyNames_ID] ASC),
CONSTRAINT [uq_PartyNames_PartyNames_GUID] UNIQUE NONCLUSTERED ([PartyNames_GUID] ASC)
) ON [PRIMARY]
GO
ALTER TABLE [dbo].[PartyNames] ADD CONSTRAINT [df_PartyNames_PartyNames_GUID] DEFAULT (newid()) FOR [PartyNames_GUID]
GO
ALTER TABLE [dbo].[PartyNames] WITH NOCHECK ADD CONSTRAINT [fk_PartyNames_Party_ID] FOREIGN KEY([Party_ID])
REFERENCES [dbo].[Party] ([Party_ID])
GO
ALTER TABLE [dbo].[PartyNames] CHECK CONSTRAINT [fk_PartyNames_Party_ID]
GO
CREATE NONCLUSTERED INDEX [ix_PartyNames_Party_ID] ON [dbo].[PartyNames]
(
[Party_ID] ASC
)
GO
Configurei o SQL Server Change Tracking em uma tabela t1 no MS SQL2008R2. Dentro de uma transação, insiro uma linha nela e a atualizo 'n' vezes. Quando examino as contagens de linhas nas tabelas de controle de alterações, ele mostra o número 'n' de linhas, enquanto o syscommitab mostra apenas 1 linha. Como o mecanismo de controle de alterações é um mecanismo síncrono e, de acordo com a documentação, espera-se que rastreie apenas "mudanças líquidas" que ocorreram em uma transação, por que a tabela de controle de alterações mostra 'n' linhas em vez de apenas 1 ? Aqui está o SQL que foi usado para examinar a contagem de linhas.
SELECT sct1.name as CT_schema,
sot1.name as CT_table,
ps1.row_count as CT_rows,
ps1.reserved_page_count*8./1024. as CT_reserved_MB,
sct2.name as tracked_schema,
sot2.name as tracked_name,
ps2.row_count as tracked_rows,
ps2.reserved_page_count*8./1024. as tracked_base_table_MB,
change_tracking_min_valid_version(sot2.object_id) as min_valid_version
FROM sys.internal_tables it
JOIN sys.objects sot1 on it.object_id=sot1.object_id
JOIN sys.schemas AS sct1 on
sot1.schema_id=sct1.schema_id
JOIN sys.dm_db_partition_stats ps1 on
it.object_id = ps1. object_id
and ps1.index_id in (0,1)
LEFT JOIN sys.objects sot2 on it.parent_object_id=sot2.object_id
LEFT JOIN sys.schemas AS sct2 on
sot2.schema_id=sct2.schema_id
LEFT JOIN sys.dm_db_partition_stats ps2 on
sot2.object_id = ps2. object_id
and ps2.index_id in (0,1)
WHERE it.internal_type IN (209, 210)
and (sot2.name='t1' or sot1.name='syscommittab')
Acima SQL cortesia de https://www.brentozar.com/archive/2014/06/performance-tuning-sql-server-change-tracking/