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 / 15720
Accepted
Aren Cambre
Aren Cambre
Asked: 2012-03-28 17:49:07 +0800 CST2012-03-28 17:49:07 +0800 CST 2012-03-28 17:49:07 +0800 CST

Por que o Postgres UPDATE levou 39 horas?

  • 772

Eu tenho uma tabela Postgres com ~ 2,1 milhões de linhas. Eu executei a atualização abaixo nele:

WITH stops AS (
    SELECT id,
           rank() OVER (ORDER BY offense_timestamp,
                     defendant_dl,
                     offense_street_number,
                     offense_street_name) AS stop
    FROM   consistent.master
    WHERE  citing_jurisdiction=1
)

UPDATE consistent.master
SET arrest_id=stops.stop
FROM stops
WHERE master.id = stops.id;

Essa consulta levou 39 horas para ser executada. Estou executando isso em um processador de laptop i7 Q720 de 4 núcleos (físicos), muita RAM, nada mais funcionando na grande maioria do tempo. Sem restrições de espaço no disco rígido. A tabela havia sido recentemente aspirada, analisada e reindexada.

Durante todo o tempo em que a consulta estava em execução, pelo menos após a WITHconclusão inicial, o uso da CPU geralmente era baixo e o HDD estava em uso 100%. O HDD estava sendo usado com tanta força que qualquer outro aplicativo rodava consideravelmente mais devagar do que o normal.

A configuração de energia do laptop estava em Alto desempenho (Windows 7 x64).

Segue a EXPLICAÇÃO:

Update on master  (cost=822243.22..1021456.89 rows=2060910 width=312)
  CTE stops
    ->  WindowAgg  (cost=529826.95..581349.70 rows=2060910 width=33)
          ->  Sort  (cost=529826.95..534979.23 rows=2060910 width=33)
                Sort Key: consistent.master.offense_timestamp, consistent.master.defendant_dl, consistent.master.offense_street_number, consistent.master.offense_street_name
                ->  Seq Scan on master  (cost=0.00..144630.06 rows=2060910 width=33)
                      Filter: (citing_jurisdiction = 1)
  ->  Hash Join  (cost=240893.51..440107.19 rows=2060910 width=312)
        Hash Cond: (stops.id = consistent.master.id)
        ->  CTE Scan on stops  (cost=0.00..41218.20 rows=2060910 width=48)
        ->  Hash  (cost=139413.45..139413.45 rows=2086645 width=268)
              ->  Seq Scan on master  (cost=0.00..139413.45 rows=2086645 width=268)

citing_jurisdiction=1exclui apenas algumas dezenas de milhares de linhas. Mesmo com essa WHEREcláusula, ainda estou operando em mais de 2 milhões de linhas.

O disco rígido é todo criptografado com TrueCrypt 7.1a. Isso atrasa um pouco as coisas, mas não o suficiente para fazer com que uma consulta demore tantas horas.

A WITHparte leva apenas cerca de 3 minutos para ser executada.

O arrest_idcampo não tinha índice para chave estrangeira. Existem 8 índices e 2 chaves estrangeiras nesta tabela. Todos os outros campos da consulta são indexados.

O arrest_idcampo não tinha restrições, exceto NOT NULL.

A tabela tem um total de 32 colunas.

arrest_idé do tipo caractere variando(20) . Percebo que rank()produz um valor numérico, mas tenho que usar o caractere variando (20) porque tenho outras linhas em citing_jurisdiction<>1que usam dados não numéricos para esse campo.

O arrest_idcampo estava em branco para todas as linhas com citing_jurisdiction=1.

Este é um laptop pessoal de ponta (a partir de 1 ano atrás). Eu sou o único usuário. Nenhuma outra consulta ou operação estava em execução. Bloquear parece improvável.

Não há gatilhos em nenhum lugar desta tabela ou em qualquer outro lugar do banco de dados.

Outras operações neste banco de dados nunca levam muito tempo. Com a indexação adequada, SELECTas consultas geralmente são bastante rápidas.

postgresql
  • 3 3 respostas
  • 28564 Views

3 respostas

  • Voted
  1. Best Answer
    JC Avena
    2014-12-09T14:34:51+08:002014-12-09T14:34:51+08:00

    Eu tive algo semelhante acontecendo recentemente com uma tabela de 3,5 milhões de linhas. Minha atualização nunca terminaria. Depois de muita experimentação e frustração, finalmente encontrei o culpado. Acabou sendo os índices na tabela sendo atualizados.

    A solução foi descartar todos os índices na tabela sendo atualizada antes de executar a instrução de atualização. Depois de fazer isso, a atualização terminou em alguns minutos. Depois que a atualização foi concluída, recriei os índices e voltei aos negócios. Isso provavelmente não vai ajudá-lo neste momento, mas pode alguém procurar respostas.

    Eu manteria os índices na tabela da qual você está extraindo os dados. Esse não precisará continuar atualizando nenhum índice e deve ajudar a encontrar os dados que você deseja atualizar. Funcionou bem em um laptop lento.

    • 31
  2. Craig Ringer
    2012-03-28T21:39:45+08:002012-03-28T21:39:45+08:00

    Seu maior problema é fazer grandes quantidades de trabalho pesado de gravação e busca em um disco rígido de laptop. Isso nunca será rápido, não importa o que você faça, especialmente se for o tipo de unidade mais lenta de 5400 RPM fornecida em muitos laptops.

    TrueCrypt retarda as coisas mais do que "um pouco" para gravações. As leituras serão razoavelmente rápidas, mas as gravações fazem o RAID 5 parecer rápido. A execução de um banco de dados em um volume TrueCrypt será uma tortura para gravações, especialmente gravações aleatórias.

    Nesse caso, acho que você estaria desperdiçando seu tempo tentando otimizar a consulta. Você está reescrevendo a maioria das linhas de qualquer maneira, e vai ser lento com sua situação de escrita horrível. O que eu recomendo é:

    BEGIN;
    SELECT ... INTO TEMPORARY TABLE master_tmp ;
    TRUNCATE TABLE consistent.master;
    -- Now DROP all constraints on consistent.master, then:
    INSERT INTO consistent.master SELECT * FROM master_tmp;
    -- ... and re-create any constraints.
    

    Suspeito que será mais rápido do que apenas descartar e recriar as restrições sozinhas, porque um UPDATE terá padrões de gravação bastante aleatórios que matarão seu armazenamento. Duas inserções em massa, uma em uma tabela não registrada e outra em uma tabela registrada no WAL sem restrições, provavelmente serão mais rápidas.

    Se você tem backups absolutamente atualizados e não se importa em restaurar seu banco de dados a partir de backups , você também pode reiniciar o PostgreSQL com o fsync=offparâmetro e full_page_writes=off temporariamente para esta operação em massa. Qualquer problema inesperado, como perda de energia ou falha do sistema operacional, deixará seu banco de dados irrecuperável enquanto o fsync=off.

    O POSTGreSQL equivalente a "sem registro" é usar tabelas não registradas. Essas tabelas não registradas serão truncadas se o banco de dados for desligado de forma imprópria enquanto estiverem sujos. O uso de tabelas não registradas reduzirá pela metade sua carga de gravação e reduzirá o número de buscas, para que elas possam ser MUITO mais rápidas.

    Como no Oracle, pode ser uma boa ideia descartar um índice e recriá-lo após uma grande atualização em lote. O planejador do PostgreSQL não consegue descobrir que uma grande atualização está ocorrendo, pausa as atualizações do índice e, em seguida, recria o índice no final; mesmo que pudesse, seria muito difícil descobrir em que ponto valeria a pena fazer isso, especialmente com antecedência.

    • 16
  3. Glenn
    2012-03-28T17:58:26+08:002012-03-28T17:58:26+08:00

    Alguém dará uma resposta melhor para o Postgres, mas aqui estão algumas observações da perspectiva Oracle que podem ser aplicadas (e os comentários são muito longos para o campo de comentários).

    Minha primeira preocupação seria tentar atualizar 2 milhões de linhas em uma transação. No Oracle, você escreveria uma imagem anterior de cada bloco que está sendo atualizado para que outra sessão ainda tenha uma leitura consistente sem ler seus blocos modificados e você tenha a capacidade de reverter. Essa é uma longa reversão sendo construída. Geralmente, é melhor fazer as transações em pequenos pedaços. Digamos 1.000 registros por vez.

    Se você tiver índices na tabela e a tabela for considerada fora de operação durante a manutenção, geralmente é melhor remover os índices antes de uma grande operação e recriá-los novamente depois. Mais barato do que tentar constantemente manter os índices a cada registro atualizado.

    O Oracle permite dicas "sem registro" em instruções para interromper o journalling. Ele acelera muito as declarações, mas deixa seu banco de dados em uma situação "irrecuperável". Portanto, você deseja fazer backup antes e fazer backup novamente imediatamente depois. Não sei se o Postgres tem opções semelhantes.

    • 2

relate perguntas

  • Posso ativar o PITR depois que o banco de dados foi usado

  • Práticas recomendadas para executar a replicação atrasada do deslocamento de tempo

  • Os procedimentos armazenados impedem a injeção de SQL?

  • Sequências Biológicas do UniProt no PostgreSQL

  • Qual é a diferença entre a replicação do PostgreSQL 9.0 e o Slony-I?

Sidebar

Stats

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

    Como ver a lista de bancos de dados no Oracle?

    • 8 respostas
  • Marko Smith

    Quão grande deve ser o mysql innodb_buffer_pool_size?

    • 4 respostas
  • Marko Smith

    Listar todas as colunas de uma tabela especificada

    • 5 respostas
  • Marko Smith

    restaurar a tabela do arquivo .frm e .ibd?

    • 10 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

    Como selecionar a primeira linha de cada grupo?

    • 6 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
    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
    pedrosanta Listar os privilégios do banco de dados usando o psql 2011-08-04 11:01:21 +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
  • Martin Hope
    bernd_k Quando devo usar uma restrição exclusiva em vez de um índice exclusivo? 2011-01-05 02:32:27 +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