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 / user-13155

gertvdijk's questions

Martin Hope
gertvdijk
Asked: 2019-07-13 05:53:32 +0800 CST

Como posso obter a última linha inserida com INSERT ... SELECT no PostgreSQL?

  • 1

Estou tentando copiar dados em lote em uma ordem específica de uma tabela para outra no PostgreSQL 12-beta2. A tabela não está usando sequências, mas contém uma chave primária exclusiva composta ( user_id, object_id).

Para determinar por onde começar o próximo lote, gostaria de começar da última linha inserida ( WHERE user_id >= last_user_id AND object_id > last_object_id).

Começando com isso:

INSERT INTO dest_table
SELECT (user_id, object_id, object_type, colN, ...) 
FROM source_table 
ORDER BY user_id, colN, object_id  -- this is indexed
LIMIT 1000  -- batch size
RETURNING user_id, object_id;

... retorna uma tabela de 1.000 tuplas. Eu gostaria de obter a última tupla inserida dele.

Eu tentei fazer um SELECT em torno dele, assim:

SELECT user_id, object_id FROM (
    INSERT INTO dest_table
    SELECT (user_id, object_id, object_type, colN, ...) 
    FROM source_table 
    ORDER BY user_id, colN, object_id  -- this is indexed
    LIMIT 1000  -- batch size
    RETURNING user_id, object_id
)
ORDER BY user_id DESC, colN DESC, object_id DESC
LIMIT 1
RETURNING user_id, object_id;

Mas isso retorna um erro de sintaxe:

ERROR:  syntax error at or near "INTO"
LINE 2: INSERT INTO dest_table
               ^

Eu também tentei RETURNING ... INTO variable conforme descrito aqui , mas isso também falha:

ERROR:  syntax error at or near "INTO"
LINE 23: RETURNING user_id, object_id INTO my_variable;
                                      ^

Preciso criar uma função para isso (por exemplo, plpgsql) ou estou perdendo algo óbvio no SQL simples que me permite fazer isso? Isso seria altamente favorável.

postgresql insert
  • 2 respostas
  • 6858 Views
Martin Hope
gertvdijk
Asked: 2019-07-09 07:03:47 +0800 CST

Como faço para que o PostgreSQL FDW empurre o LIMIT para o servidor de back-end (único)?

  • 3

Configurei um servidor PostgreSQL FDW com a seguinte tabela, fragmentada por user_idmais de quatro servidores:

CREATE TABLE my_big_table
(
    user_id bigint NOT NULL,
    serial bigint NOT NULL,         -- external, incrementing only
    some_object_id bigint NOT NULL,
    timestamp_ns bigint NOT NULL,
    object_type smallint NOT NULL,
    other_type smallint NOT NULL,
    data bytea
) PARTITION BY HASH (user_id) ;
CREATE SERVER shardA
    FOREIGN DATA WRAPPER postgres_fdw
    OPTIONS (host '192.168.200.11', port '5432', dbname 'postgres', fetch_size '10000');
 .
 .
 .
CREATE SERVER shardD
    FOREIGN DATA WRAPPER postgres_fdw
    OPTIONS (host '192.168.200.14', port '5432', dbname 'postgres', fetch_size '10000');
create foreign table my_big_table_mod4_s0 partition of my_big_table
    FOR VALUES WITH (MODULUS 4, REMAINDER 0) server shardA
    OPTIONS (table_name 'my_big_table_mod4_s0');
 .
 .
 .
create foreign table my_big_table_mod4_s3 partition of my_big_table
    FOR VALUES WITH (MODULUS 4, REMAINDER 3) server shardD
    OPTIONS (table_name 'my_big_table_mod4_s3');

Nos servidores de back-end, configurei uma tabela com vários índices, seus dados agrupados (user_id, serial)em várias partições. No entanto, não acho que esses detalhes sejam muito relevantes para minha pergunta real.

A consulta comum no meu cluster está no padrão de:

SELECT * from my_big_table
WHERE
  user_id = 12345     -- only 1 user, always! --> single foreign server.
ORDER BY serial DESC  -- get 'newest' 90% of the time, 10% ASC
LIMIT 1000;           -- max limit 1000, sometimes less

Para usuários com < 1000 registros: tudo bem, sem problemas.

Para usuários com > 100.000 registros, vejo o problema que leva a um desempenho ruim: explainmostra LIMIT e a classificação acontece no FDW, não é pressionado. Por quê?

 Limit  (cost=927393.08..927395.58 rows=1000 width=32)
   Output: my_big_table_mod4_s0.serial, my_big_table_mod4_s0.some_object_id, my_big_table_mod4_s0.timestamp_ns, my_big_table_mod4_s0.object_type, my_big_table_mod4_s0.other_type, (length(my_big_table_mod4_s0.data))
   ->  Sort  (cost=927393.08..931177.06 rows=1513592 width=32)
         Output: my_big_table_mod4_s0.serial, my_big_table_mod4_s0.some_object_id, my_big_table_mod4_s0.timestamp_ns, my_big_table_mod4_s0.object_type, my_big_table_mod4_s0.other_type, (length(my_big_table_mod4_s0.data))
         Sort Key: my_big_table_mod4_s0.serial DESC
         ->  Foreign Scan on public.my_big_table_mod4_s0  (cost=5318.35..844404.46 rows=1513592 width=32)
               Output: my_big_table_mod4_s0.serial, my_big_table_mod4_s0.some_object_id, my_big_table_mod4_s0.timestamp_ns, my_big_table_mod4_s0.object_type, my_big_table_mod4_s0.other_type, length(my_big_table_mod4_s0.data)
               Remote SQL: SELECT serial, some_object_id, timestamp_ns, object_type, other_type, data FROM public.my_big_table_mod4_s0 WHERE ((user_id = 4560084))
 JIT:
   Functions: 3
   Options: Inlining true, Optimization true, Expressions true, Deforming true

O takeaway do acima é:

  • Servidor de back-end único selecionado: OK! (resolvido com isso )
  • Remote SQL: SELECT [...]indica que não há ORDER BY, nem LIMIT. Problema.

Executado no servidor back-end mostra isso diretamente:

 Limit  (cost=1.74..821.42 rows=1000 width=32)
   Output: my_big_table_mod4_s0_part123.serial, my_big_table_mod4_s0_part123.some_object_id, my_big_table_mod4_s0_part123.timestamp_ns, my_big_table_mod4_s0_part123.object_type, my_big_table_mod4_s0_part123.other_type, (length(my_big_table_mod4_s0_part123.data))
   ->  Append  (cost=1.74..1240669.45 rows=1513592 width=32)
         ->  Index Scan Backward using my_big_table_mod4_s0_part123_pkey on public.my_big_table_mod4_s0_part123  (cost=0.43..290535.67 rows=355620 width=32)
               Output: my_big_table_mod4_s0_part123.serial, my_big_table_mod4_s0_part123.some_object_id, my_big_table_mod4_s0_part123.timestamp_ns, my_big_table_mod4_s0_part123.object_type, my_big_table_mod4_s0_part123.other_type, length(my_big_table_mod4_s0_part123.data)
               Index Cond: (my_big_table_mod4_s0_part123.user_id = 4560084)
         ->  Index Scan Backward using [... other partitions ...]

O que eu tentei:

  • Como o FDW ainda está ativo em desenvolvimento, tentei usar uma versão mais recente: 11.4 e 12-beta2 tanto para FDW quanto para servidores backend. Nenhuma diferença observada.
  • Executando ANALYZE na tabela externa (na instância FDW). Leva muito tempo; parece que está cheio de tabelas digitalizando a tabela remota? Nenhuma diferença no planejamento de consultas.
  • Alterando o valor de fetch_sizeno objeto SERVER remoto. Nenhuma diferença.
  • Definido use_remote_estimate=trueno objeto SERVER remoto. Nenhuma diferença.
  • Definido fdw_tuple_cost=100no objeto SERVER remoto. A classificação agora acontece no servidor remoto, mas LIMIT ainda não foi pressionado.
  • Procurando online por outras pessoas vendo isso, mostrando apenas este post relacionado: Missed LIMIT cláusula pushdown na API FDW

    Mas este tópico menciona commits corrigindo isso em 9.7 e outros enfeites, mas estou usando 11.4 e 12-beta2. Ou eu entendo isso errado?

    E post: Estimativa de custo estranho para tabelas estrangeiras mostra um bom exemplo de ajuste de FDW, mas infelizmente não cobre meu problema com LIMITs.

  • Dando uma rápida olhada no código fonte do PostgreSQL, notei esta declaração, talvez relevante para FDW, talvez não ( source ).

    Não podemos enviar subseleções contendo LIMIT/OFFSET para os trabalhadores, pois não há garantia de que a ordem das linhas seja totalmente determinística, e a aplicação de LIMIT/OFFSET levará a resultados inconsistentes no nível superior. (Em alguns casos, onde o resultado é ordenado, podemos relaxar essa restrição. Mas atualmente não parece valer a pena gastar um esforço extra para fazê-lo.)

  • Dando outra olhada no código-fonte, encontrei este commit promissor ( d50d172e51 ):

    Isso fornece a capacidade do postgres_fdw de lidar com comandos SELECT para que 1) pule a etapa LockRows (se houver) (observe que isso é seguro, pois executa o bloqueio antecipado) e 2) reduz as restrições LIMIT e/ou OFFSET (se houver) ) para o lado remoto. Isso não lida com os casos INSERT/UPDATE/DELETE.

    Ele adiciona um caso de teste de unidade exatamente para o meu caso!

    -- and both ORDER BY and LIMIT can be shipped
    EXPLAIN (VERBOSE, COSTS OFF)
      SELECT * FROM ft1 t1 WHERE t1.c1 === t1.c2 order by t1.c2 limit 1;
                                                                            QUERY PLAN                                                                         
    ------------------------------------------------------------------------------------------------------------------------------------------------------------
    Foreign Scan on public.ft1 t1
      Output: c1, c2, c3, c4, c5, c6, c7, c8
      Remote SQL: SELECT "C 1", c2, c3, c4, c5, c6, c7, c8 FROM "S 1"."T 1" WHERE (("C 1" OPERATOR(public.===) c2)) ORDER BY c2 ASC NULLS LAST LIMIT 1::bigint
    

    que deve fazer parte do 12-beta2, que já estou rodando...

Percebi que deveria usar índices na ordem DESC aqui, mas isso não é tão relevante agora.

performance sharding
  • 1 respostas
  • 2606 Views
Martin Hope
gertvdijk
Asked: 2019-06-18 14:27:48 +0800 CST

Poda de partição eficiente com ORDER BY na mesma coluna que PARTITION BY RANGE + LIMIT?

  • 0

Eu configurei uma tabela no MariaDB (10.4.5, atualmente RC) com o InnoDB usando particionamento por uma coluna cujo valor é somente incrementado e novos dados são sempre inseridos no final. Nesse caso, o particionamento faz sentido para acelerar algumas consultas e manter partições novas/ativas em unidades rápidas e antigas/arquivadas em discos giratórios lentos. Para acelerações de inserção está funcionando muito bem! (Uma espécie de abordagem TimescaleDb, mas sem tempo e sem PostgreSQL.)

SELECTs por intervalo na mesma coluna também funcionam bem; ele só começará a ler (o índice de) as partições do intervalo especificado. Tudo legal até agora.

Agora, também tenho consultas que não têm uma cláusula nessa coluna, mas são ordenadas de forma decrescente por essa coluna (ou seja, dados novos primeiro), junto com um limite, que normalmente atingiria apenas uma ou duas partições mais recentes (rápidas, em cache índice). No entanto, parece que o MySQL/MariaDB começa a abrir partições do primeiro ao último, não importa qual seja a ordem especificada. É realmente tão burro? Além disso, não consegui encontrar mais ninguém com essa dúvida, o que me preocupa um pouco. (Às vezes significa que estou perdendo algo realmente óbvio.)

Para ficar mais concreto aqui - para testes, tenho a seguinte tabela:

CREATE TABLE `mytable` (
  `user_id` bigint(20) unsigned NOT NULL,
  `my_id` bigint(20) unsigned NOT NULL,
  `data` varbinary(123) DEFAULT NULL,
  PRIMARY KEY (`user_id`,`my_id`),
  UNIQUE KEY `my_id_idx` (`my_id`)  -- I was hoping this one could help me
) ENGINE=InnoDB ROW_FORMAT=COMPACT
 PARTITION BY RANGE (`my_id`)
(PARTITION `p0` VALUES LESS THAN (10000000) ENGINE = InnoDB,
 PARTITION `p10M` VALUES LESS THAN (20000000) ENGINE = InnoDB,
 PARTITION `p20M` VALUES LESS THAN (30000000) ENGINE = InnoDB,
 PARTITION `p30M` VALUES LESS THAN (40000000) ENGINE = InnoDB,
 [...]
) 

E eu executo uma consulta como:

SELECT 
    user_id,
    my_id,
    LENGTH(data) AS data_len
FROM
    mytable
    -- tried to optimize with index hints:
    -- USE INDEX FOR ORDER BY (MY_ID_IDX)
    -- USE INDEX FOR ORDER BY (PRIMARY)
    -- USE INDEX FOR ORDER BY (MY_IDX, PRIMARY)
WHERE
    user_id = 1234567
ORDER BY my_id DESC
LIMIT 10;

Descobri que ele começa a procurar TODOS os dados user_id = 1234567primeiro, mostrando primeiro a carga pesada de E / S nos discos giratórios, depois finalmente chegando ao armazenamento rápido para obter o conjunto completo e cortando as últimas LIMIT 10linhas ... o que estavam todos em armazenamento rápido, então perdemos minutos de tempo para nada! Hum.

Meus dados são muito grandes e não podemos ter todos os índices na memória - contamos com 'o suficiente' do índice no disco para ser armazenado em cache na camada de armazenamento. Mas mesmo que todos os índices couberem no cache, os dados precisam vir de discos e alguns usuários têm uma quantidade ENORME de dados aqui (> 10 milhões de linhas) e é simplesmente ineficiente fazer essa classificação na memória assim. Então, espero encontrar uma maneira de fazer com que o MariaDB procure a última quantidade LIMIT de linhas e pare de ler.

Como humano, você começaria a procurar na última partição primeiro, porque ela ORDER BY my_id DESCe as partições mais recentes contêm os valores mais altos para ela. No entanto, como eu digo ao MySQL/MariaDB para fazer isso?

explain partitionsresultado (para todas as variantes USE INDEX listadas acima é o mesmo):

  select_type: SIMPLE
        table: mytable
   partitions: p0M,p10M,p20M,p30M, ... (~ hundred here)
         type: ref
possible_keys: PRIMARY
          key: PRIMARY
      key_len: 8
          ref: const
         rows: 9999999 (worst-case)
        Extra: Using where

Na verdade, ao contrário do que eu esperava, nem está tendo melhor desempenho se fizer a consulta em ordem crescente , usando a partição first-to-new. Ele ainda solicitará todos os índices de todas as partições e descobrirá que só precisava de um ...

Ouvi algo sobre um índice global para partições em versões futuras do MySQL, mas duvido que realmente ajude aqui, dado o tamanho enorme ..., e já recebeu a dica pelo próprio layout de particionamento no meu caso. A informação que encontro sobre 'remoção de partição' parece não ter relação com a ordenação das leituras; apenas sobre cláusulas na consulta.

Qualquer ajuda é apreciada.:-)

As partições mais novas serão criadas dinamicamente e não é realmente viável dar uma dica sobre uma partição específica. Minha situação é que as partições "mais recentes" são rápidas, "mais antigas" são "lentas", "mais antigas" são "super lentas" - assumindo que nada armazenado em cache na camada de armazenamento é demais. Além disso, estou usando um proxy (SPIDER) em uma máquina separada que deve fornecer aos clientes uma única interface para consulta, sem precisar saber sobre o layout de particionamento dos back-ends, então prefiro uma maneira de fazer isso ' automático'.

mysql mariadb
  • 1 respostas
  • 823 Views
Martin Hope
gertvdijk
Asked: 2012-10-05 05:37:59 +0800 CST

Por que pt-table-checksum dá status de saída 0 se o escravo estiver inacessível?

  • 1

Estou usando a pt-table-checksumversão 2.1.4para verificar minha configuração mestre-escravo. No caso de eu esquecer de configurar os privilégios corretos no escravo, ele escreve um erro stderrcomo este:

# pt-table-checksum -d employees
Cannot connect to h=node03.mydomain.local                                 <== error
            TS ERRORS  DIFFS     ROWS  CHUNKS SKIPPED    TIME TABLE
10-04T15:33:33      0      0        9       1       0   0.014 employees.departments
[...]

No entanto, o status de saída dele é 0.

# echo $?
0

As diferenças numéricas que ele encontrará são sempre zero, pois não há nada para comparar. E sim, a documentação diz para sair com status 0se nenhuma diferença ou erro for relatado. Mas isso não faz sentido na maioria dos casos.

Existe uma maneira de pt-table-checksumnão falhar silenciosamente e relatar isso como uma falha geral? Devo registrar um bug ou isso é configurável?

Prova ser confuso para mais usuários, por exemplo nesta questão: "pt-table-checksum help required" .

percona-tools
  • 1 respostas
  • 182 Views
Martin Hope
gertvdijk
Asked: 2012-10-05 03:32:12 +0800 CST

Tenho que filtrar a tabela percona.checksums na replicação para uso com pt-table-checksum?

  • 2

Eu configurei a replicação do MySQL, um mestre e um escravo. Agora estou apenas começando a verificar a integridade dos dados em ambos os lados usando o arquivo pt-table-checksum. Ferramenta maravilhosa para detectar quaisquer alterações ou desvios no escravo.

Pelo que entendi de sua documentação , ele é executado no mestre, grava somas de verificação na percona.checksumstabela e é executado de maneira semelhante nos escravos conectados (detectados automaticamente) usando uma conexão MySQL remota regular. No entanto, a percona.checksumstabela também é replicada! Se os dados forem diferentes no escravo, as somas de verificação do mestre podem ser sobrescritas no escravo e não serem detectadas.

Agora, estou preocupado que isso possa estar causando meus falsos negativos observados na detecção de alterações.

As salvaguardas pt-table-checksumforam implementadas para impedir a replicação na percona.checksumsmesa?

  • Em caso afirmativo, como isso funciona? (até onde posso ver, não é possível alterar filtros de replicação assim) Isso pode me ajudar a identificar algum outro motivo para minhas observações (veja abaixo).
  • Caso contrário, como posso ter certeza de que o conteúdo dessa tabela reflete as somas de verificação desse servidor específico? Devo colocar um filtro de replicação no lugar? Na verdade, isso é desencorajado pela documentação do kit de ferramentas da Percona.

Observações reais

Eu vi uma ocorrência em minha configuração de teste em que, de alguma forma, a execução pt-table-checksumnão detectou a alteração feita deliberadamente no escravo. A inspeção do conteúdo da tabela de soma de verificação mostrou as somas de verificação do mestre. A execução da ferramenta no próprio escravo mostrou que as somas de verificação deveriam ser diferentes! Isso me faz acreditar que há uma condição de corrida acontecendo e a razão pela qual isso é difícil de reproduzir.

outra hipótese

Suponha que o escravo tenha se desviado e a conexão de rede esteja inativa por um curto período de tempo pt-table-checksum. Ele mostrará que não consegue se conectar ao escravo na stderrsaída, mas não falhará. Pouco tempo depois, a rede é restaurada e a replicação continua, copiando o conteúdo do mestre da tabela percona.checksums. Em seguida, executar pt-table-checksum --replicate-check-only, fornecerá falsos negativos. Estou bem aqui? Em caso afirmativo, como posso evitar isso neste caso?

Este é um servidor/cliente MySQL regular usando o kit de ferramentas da Percona.

Versões:

  • pt-table-checksum 2.1.4
  • Cliente MySQL: 5.5.24
  • Servidor MySQL: 5.5.24-0ubuntu0.12.04.1-log (Ubuntu 12.04)
mysql replication
  • 1 respostas
  • 1075 Views

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