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 / 175227
Accepted
Nick.McDermaid
Nick.McDermaid
Asked: 2017-06-02 17:57:08 +0800 CST2017-06-02 17:57:08 +0800 CST 2017-06-02 17:57:08 +0800 CST

Query se transformou em um monstro devorador de CPU

  • 772

Eu tenho um SP cujo tempo de execução passou de 5 minutos > 20 minutos > 30 minutos > 53 minutos ao longo de quatro dias

As esperas estavam mostrando CPU crescente e status suspenso

Eu isolei uma única consulta que fixa a CPU

UPDATE thing.table
SET YYYYMM = 
CASE 
  WHEN 
    DAY(SnapshotDate) = 1
    OR 
  SnapshotDate = (SELECT MAX(SnapshotDate) FROM thing.table) 
  THEN CAST(FORMAT(DATEADD(day,-1,snapshotdate),'yyyyMM') AS INT)
  ELSE NULL
END

Executei novamente, adicionando WITH (RECOMPILE)no final - sem diferença

Eu corri UPDATE STATISTICS thing.table- nenhuma diferença

Seria interessante executá-lo e obter o plano real, mas não quero prender a CPU por uma hora. Verifiquei sys.dm_exec_cached_plans, mas parece ter apenas o plano estimado, não o plano real

Eu reescrevi usando CONVERTem vez de FORMAT(porque desconfio de coisas novas) - nenhuma diferença

Então eu reescrevi assim e levei a execução de volta para alguns segundos:

BEGIN TRAN;

UPDATE thing.table
SET YYYYMM = NULL;

UPDATE thing.table
SET YYYYMM = CAST(FORMAT(DATEADD(day,-1,snapshotdate),'yyyyMM') AS INT)
WHERE 
(
DAY(SnapshotDate) = 1 
OR
SnapshotDate = (SELECT MAX(SnapshotDate) FROM thing.table) 
);

COMMIT TRAN;

A tabela tem cerca de 150.000 registros. É bem possível que recentemente tenha muito mais registros despejados nele, distorcendo as estatísticas, mas por que consertar isso WITH(RECOMPILE)e não? UPDATE STATISTICSEle tira um instantâneo diário e possivelmente o número de registros aumentou devido ao final do mês.

Então as perguntas são:

  1. O plano de consulta real está armazenado em qualquer lugar?, para me poupar de executá-lo interativamente?
  2. Normalmente, quando uma consulta de repente leva uma eternidade, as estatísticas ficam obsoletas, mas esse não parece ser o caso aqui

Esta é a minha versão do SQL Server

Microsoft SQL Server 2014 - 12.0.4100.1 (X64) 20 de abril de 2015 17:29:27 Copyright (c) Microsoft Corporation Standard Edition (64 bits) no Windows NT 6.3 (Build 9600: ) (Hypervisor)

Aqui estão os planos de consulta lenta e rápida. Não é surpresa que eles sejam diferentes porque estão fazendo coisas diferentes:

Plano lento:

Plano de consulta lenta

Plano Rápido:

Plano de consulta rápida

Percebo que o slowpoke usa uma junção de loop e o fasty usa uma correspondência de hash.

Percebo que a pequena perna da junção do loop tem filtro

[Expr1006]=DB.thing.table.[SnapshotDate]. Talvez isso não fosse mais tão pequeno?

sql-server sql-server-2014
  • 2 2 respostas
  • 79 Views

2 respostas

  • Voted
  1. Best Answer
    Joe Obbish
    2017-06-02T18:44:31+08:002017-06-02T18:44:31+08:00

    A primeira consulta é tão lenta porque fará uma varredura completa da tabela thing.tablepara cada linha dessa tabela para a qual o DAY(SnapshotDate) <> 1. Portanto, se você tiver 100 mil linhas na tabela, no pior caso, fará 100 mil varreduras, o que significa ler 10 bilhões de linhas. Se a tabela for pequena o suficiente, ela permanecerá na memória para que sua consulta paralela pareça queimar na CPU.

    Você pode dizer observando o plano de consulta com cuidado. A varredura está no lado interno de uma junção de loop aninhada. Se essa não é sua xícara de chá, você pode tentar estatísticas de consulta ao vivo para ver a consulta enquanto ela é executada. Dessa forma, você pode obter algumas informações do plano real sem precisar concluir a consulta. Não há como economizar em planos reais antigos sem configurar eventos estendidos.

    A segunda consulta é mais rápida porque o otimizador de consultas é mais livre para reorganizar os elementos da consulta devido à falta da CASEexpressão. Em vez de calcular a subconsulta MAX(SnapshotDate)uma vez por linha, o cálculo é feito uma vez por consulta.

    Você definitivamente desejará corrigir essa consulta de alguma forma ou o tempo de execução continuará a crescer quadraticamente com o número de linhas na tabela. Uma solução seria adicionar um índice à SnapshotDatecoluna. A subconsulta ainda será executada uma vez para cada linha, mas obter o valor máximo será uma operação muito barata. Uma maneira melhor é salvar o valor da subconsulta em uma variável local e usá-la em sua UPDATEconsulta. A menos que você tenha que se preocupar com a simultaneidade, isso não deve ser um problema.

    Você também pode manter a correção que encontrou, se quiser. Uma sugestão que pode ajudar em alguns casos (dependendo da estrutura da tabela) seria adicionar uma cláusula where ao seu first UPDATE:

    UPDATE thing.table
    SET YYYYMM = NULL
    WHERE YYYYMM IS NOT NULL;
    
    • 4
  2. Madhu
    2017-06-03T03:56:09+08:002017-06-03T03:56:09+08:00

    Eu recomendaria quebrar a consulta da seguinte forma:

    --select MAX(SnapshotDate) only once
    DECLARE @MAX_SnapshotDate datetime  --use the appropriate data type
    SELECT @MAX_SnapshotDate=MAX(SnapshotDate) FROM thing.table
    
    --Create computed column
    ALTER TABLE thing.table
    ADD DAY_SnapshotDate as (DAY(SnapshotDate)) PERSISTED
    
    UPDATE thing.table
    SET YYYYMM = NULL;
    
    UPDATE thing.table
    SET YYYYMM = CAST(FORMAT(DATEADD(day,-1,snapshotdate),'yyyyMM') AS INT)
    WHERE 
    SnapshotDate = @MAX_SnapshotDate
    
    UPDATE thing.table
    SET YYYYMM = CAST(FORMAT(DATEADD(day,-1,snapshotdate),'yyyyMM') AS INT)
    WHERE 
    DAY_SnapshotDate = 1 
    
    • 0

relate perguntas

  • SQL Server - Como as páginas de dados são armazenadas ao usar um índice clusterizado

  • Preciso de índices separados para cada tipo de consulta ou um índice de várias colunas funcionará?

  • Quando devo usar uma restrição exclusiva em vez de um índice exclusivo?

  • Quais são as principais causas de deadlocks e podem ser evitadas?

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

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