AskOverflow.Dev

AskOverflow.Dev Logo AskOverflow.Dev Logo

AskOverflow.Dev Navigation

  • Início
  • system&network
  • Ubuntu
  • Unix
  • DBA
  • Computer
  • Coding
  • LangChain

Mobile menu

Close
  • Início
  • system&network
    • Recentes
    • Highest score
    • tags
  • Ubuntu
    • Recentes
    • Highest score
    • tags
  • Unix
    • Recentes
    • tags
  • DBA
    • Recentes
    • tags
  • Computer
    • Recentes
    • tags
  • Coding
    • Recentes
    • tags
Início / dba / Perguntas / 264128
Accepted
QFirstLast
QFirstLast
Asked: 2020-04-03 00:07:27 +0800 CST2020-04-03 00:07:27 +0800 CST 2020-04-03 00:07:27 +0800 CST

por que uma consulta simples teria um desempenho ruim no MS SQL Server 2014 ou 2014SP3 quando em outras versões ele funciona bem?

  • 772

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 insira a descrição da imagem aqui E aqui está o plano de execução nas outras versões do SQL Server, 2012, 2016, 2019 insira a descrição da imagem aqui

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
performance sql-server-2014
  • 1 1 respostas
  • 93 Views

1 respostas

  • Voted
  1. Best Answer
    Josh Darnell
    2020-04-03T04:07:04+08:002020-04-03T04:07:04+08:00

    Você precisa habilitar o sinalizador de rastreamento documentado e com suporte 4199 (que permite correções do otimizador de consulta) para corrigir esse problema.

    Você pode habilitá-lo no nível de consulta para testá-lo, mas isso requer permissões de sysadmin (que esperamos que seu aplicativo não tenha). Um argumento bastante convincente pode ser feito para ativar isso globalmente (como um sinalizador de rastreamento de inicialização), você pode ler algumas discussões sobre isso aqui: Sinalizador de rastreamento 4199 - Ativar globalmente?


    Consegui reproduzir seu problema usando os seguintes dados de teste:

    INSERT INTO dbo.Party
        (Party_GUID)
    SELECT TOP (1900000)
        NEWID()
    FROM master.dbo.spt_values v1
    CROSS JOIN master.dbo.spt_values v2;
    
    INSERT INTO dbo.PartyNames
        (Party_ID, PartyNames_GUID)
    SELECT TOP (1300000)
        Party_ID,
        NEWID()
    FROM dbo.Party;
    

    Obter um plano estimado para a consulta de teste produz o plano inválido:

    captura de tela do plano ruim

    O otimizador escolhe varrer o índice clusterizado dbo.PartyNamesporque, por algum motivo, ele acha que cada linha dbo.PartyNamesserá uma correspondência para a linha recuperada de dbo.Party.

    Adicionar OPTION (QUERYTRACEON 4199)ao final da consulta corrige esse raciocínio defeituoso e produz o bom plano:

    captura de tela do bom plano

    Para obter mais informações sobre TF 4199, consulte este KB: SQL Server otimizador de consulta hotfix trace flag 4199 service model


    Uma solução alternativa é usar o estimador de cardinalidade legado com sinalizador de rastreamento 9481, que também produz o plano bom.

    • 2

relate perguntas

  • Existe um ganho de desempenho ao manipular dados com procedimentos armazenados em vez de alimentá-los em funções após a recuperação?

  • Como você ajusta o MySQL para uma carga de trabalho pesada do InnoDB?

  • Como determinar se um Índice é necessário ou necessário

  • Onde posso encontrar o log lento do mysql?

  • Como posso otimizar um mysqldump de um banco de dados grande?

Sidebar

Stats

  • Perguntas 205573
  • respostas 270741
  • best respostas 135370
  • utilizador 68524
  • Highest score
  • respostas
  • Marko Smith

    conectar ao servidor PostgreSQL: FATAL: nenhuma entrada pg_hba.conf para o host

    • 12 respostas
  • Marko Smith

    Como fazer a saída do sqlplus aparecer em uma linha?

    • 3 respostas
  • Marko Smith

    Selecione qual tem data máxima ou data mais recente

    • 3 respostas
  • Marko Smith

    Como faço para listar todos os esquemas no PostgreSQL?

    • 4 respostas
  • Marko Smith

    Listar todas as colunas de uma tabela especificada

    • 5 respostas
  • Marko Smith

    Como usar o sqlplus para se conectar a um banco de dados Oracle localizado em outro host sem modificar meu próprio tnsnames.ora

    • 4 respostas
  • Marko Smith

    Como você mysqldump tabela (s) específica (s)?

    • 4 respostas
  • Marko Smith

    Listar os privilégios do banco de dados usando o psql

    • 10 respostas
  • Marko Smith

    Como inserir valores em uma tabela de uma consulta de seleção no PostgreSQL?

    • 4 respostas
  • Marko Smith

    Como faço para listar todos os bancos de dados e tabelas usando o psql?

    • 7 respostas
  • Martin Hope
    Jin conectar ao servidor PostgreSQL: FATAL: nenhuma entrada pg_hba.conf para o host 2014-12-02 02:54:58 +0800 CST
  • Martin Hope
    Stéphane Como faço para listar todos os esquemas no PostgreSQL? 2013-04-16 11:19:16 +0800 CST
  • Martin Hope
    Mike Walsh Por que o log de transações continua crescendo ou fica sem espaço? 2012-12-05 18:11:22 +0800 CST
  • Martin Hope
    Stephane Rolland Listar todas as colunas de uma tabela especificada 2012-08-14 04:44:44 +0800 CST
  • Martin Hope
    haxney O MySQL pode realizar consultas razoavelmente em bilhões de linhas? 2012-07-03 11:36:13 +0800 CST
  • Martin Hope
    qazwsx Como posso monitorar o andamento de uma importação de um arquivo .sql grande? 2012-05-03 08:54:41 +0800 CST
  • Martin Hope
    markdorison Como você mysqldump tabela (s) específica (s)? 2011-12-17 12:39:37 +0800 CST
  • Martin Hope
    Jonas Como posso cronometrar consultas SQL usando psql? 2011-06-04 02:22:54 +0800 CST
  • Martin Hope
    Jonas Como inserir valores em uma tabela de uma consulta de seleção no PostgreSQL? 2011-05-28 00:33:05 +0800 CST
  • Martin Hope
    Jonas Como faço para listar todos os bancos de dados e tabelas usando o psql? 2011-02-18 00:45:49 +0800 CST

Hot tag

sql-server mysql postgresql sql-server-2014 sql-server-2016 oracle sql-server-2008 database-design query-performance sql-server-2017

Explore

  • Início
  • Perguntas
    • Recentes
    • Highest score
  • tag
  • help

Footer

AskOverflow.Dev

About Us

  • About Us
  • Contact Us

Legal Stuff

  • Privacy Policy

Language

  • Pt
  • Server
  • Unix

© 2023 AskOverflow.DEV All Rights Reserve