Oracle 11g: melhorias de desempenho das pastilhas

8

Eu tenho uma tabela de 500 milhões de linhas (e em crescimento)

Fiz o seguinte para melhorar o desempenho das pastilhas:

No lado do banco de dados:

  • caiu todos os índices e restrições
  • log desativado

No lado da aplicação:

  • mudou de entidades gerenciadas JPA para consultas de inserção nativas, adicionou a dica APPEND Oracle à consulta
  • tentou confirmar em lotes por 1k / 2k / 3k de linhas
  • tentou escrever em paralelo (várias threads, contagem de threads = a contagem principal no servidor) em uma tabela

Isso me deu cerca de 300 linhas por segundo

Além disso, tentei:

  • escreva em paralelo em lotes para várias tabelas (para agrupar e retornar resultados usando UNION)

Isso me deu cerca de 1 mil linhas por segundo, mas em tabelas vazias. Mas quando preenchi tabelas com dados fictícios (200 milhões cada), a velocidade das inserções caiu para 250 - 300 por segundo.

Alguém poderia sugerir o que mais posso fazer para acelerar as inserções? Basicamente, quero entender primeiro o que é (o que poderia ser) o gargalo.

UPD: a tabela é particionada pela data de inserção, a tabela possui cerca de 60 colunas - a maioria das colunas é VARCHAR2 (2000 BYTE)

à deriva
fonte
Você sabe que, com o log desativado, uma falha de mídia entre a carga e a conclusão do primeiro backup subsequente deixará a tabela inteira ou seções dela no caso de uma inserção de caminho direto, irrecuperável, certo?
precisa
11
(1) Apenas uma sessão pode ANEXAR a qualquer momento em uma mesa. (2) a /*+APPEND*/dica é ignorada nas inserções de linha única (se você não precisa INSERT INTO ... SELECTse preocupar em acrescentar). (3) Você deve configurar um exemplo do SQL * Loader direct=truepara estabelecer uma linha de base, conforme sugerido por @parsifal.
Vincent Malgrat
Você está executando em hardware real ou em uma máquina virtual? Se uma VM, os arquivos do disco são escassos (ou seja: não estão totalmente pré-alocados)? Além disso, edite sua pergunta com a saída de um relatório statspack ou awr (seção principais esperas).
`` #
Qual problema / necessidade o particionamento por data de inserção resolve / satisfaz?
27713 Brian
Qual é a fonte dos seus dados para esta tabela? É um carregamento em lote de um arquivo ASCII ou é gerado pelo usuário ou algo mais. Por favor, seja específico.
RMAN Express 26/03

Respostas:

5

Acabei de ver a atualização, tabela de 60-col com principalmente campos VARCHAR (2k) - ou seja, (potencialmente) uma tabela de monstros.

Primeiras coisas primeiro ...

Você precisa entender seu gargalo PRIMEIRO. No lado do aplicativo, volte para a solução de inserção em lote de thread único (1/2/3k de cada vez) e comece a executá-la, faça o login na máquina do DB e execute um 'top' - veja quanto tempo que o processo do banco de dados está demorando E quanto (se houver) wa% do tempo a máquina está mostrando.

Se top estiver mostrando QUALQUER wa% de tempo, isso significa que seu banco de dados está vinculado a E / S e você provavelmente precisará considerar várias máquinas de banco de dados (shards) ou lançar SSDs na máquina host.

É isso aí; sua pesquisa para aqui. Não importa a quantidade de CPU que o banco de dados estava usando ou a saturação do seu aplicativo cliente; se você estiver enfrentando problemas de latência de E / S no banco de dados do host, será o mais rápido possível.

DICA Se as alterações de hardware estiverem fora de questão, dependendo do sistema de arquivos que você está executando (Linux), tente desabilitar o log ou a gravação de metadados para o banco de dados para melhorar um pouco o desempenho no nível do sistema de arquivos. Você pode fazer algo semelhante no NTFS, mas isso só lhe dará um pequeno impulso. Isso não será 2x.

Agora, segundas coisas depois ...

Digamos que você tenha quase nenhum tempo wa wa, mas sua CPU está totalmente vinculada ao processo do banco de dados. Sua única opção agora é introduzir mais máquinas de banco de dados (shards) e dividir o trabalho.

Novamente, você terminou sua pesquisa, se este for o caso. Nada que você possa fazer para ajustar a CPU para ir mais rápido.

Por fim, terceira coisa ... terceira ...

Digamos que o DB não esteja fazendo muita coisa. Em seguida, vá para a máquina cliente executando a inserção em lote e verifique a carga da CPU - ela está vinculada? Nesse caso, inicie mais algumas máquinas fazendo exatamente as mesmas inserções de lote e veja se é possível obter uma rampa linear.

Se a CPU não estiver vinculada, inicie mais alguns threads na mesma máquina até que ela esteja vinculada e veja como o DB é dimensionado.

Eu acho que você já deve ter tentado isso, então meu palpite é que o host do seu cliente já estava vinculado (e mais threads não farão diferença) ou o banco de dados já estava atingindo seu limite e não pode escalar mais.

Termo aditivo

Fazer inserções brutas em uma tabela não indexada que não contém lixo é essencialmente uma operação APPEND que deve estar indo tão rápido quanto o disco pode lidar com as gravações.

Criar mais tabelas na mesma máquina host não ajudará, se alguma coisa aumentar o seu disco procura (para acessar as outras tabelas do disco a serem anexadas) e atrasará as coisas.

É fundamental descobrir primeiro esse gargalo, para que possamos otimizar o inferno.

Espero que ajude! Mantenha-nos informados.

Riyad Kalla
fonte
2
Por que você não mencionou o awr ou o statspack?
Philᵀᴹ
Com uma dica de acréscimo, todos, exceto um desses encadeamentos, ficarão ociosos devido ao bloqueio exclusivo. Eu não acho que esse código esteja em um estágio de eficiência em que é necessário o ajuste no nível do sistema - é a própria metodologia que é falha.
precisa
Pensando melhor, acredito que sua abordagem tem uma falha fundamental. Se os Viktors tentassem o método de inserção em lote de thread único e tivessem tempos de espera de E / S, isso poderia ser causado por um método de inserção ineficiente e comprometimento excessivo (a sincronização do arquivo de log aguarda). O passo mais importante deve ser entender os mecanismos do Oracle e escolher o mais apropriado primeiro, com certeza?
precisa
@DavidAldridge Viktors esclareceu que ele havia desativado o registro (e os índices), considerando que, presumi que não havia muito mais o DB estava fazendo além de transmitir os dados inseridos diretamente para o arquivo da tabela, e foi por isso que ele pulei direto para olhar Espera de E / S. Talvez exista mais que a Oracle esteja fazendo isso deveria / poderia ser desativado - esse é um bom ponto de investigação, não conheço as profundezas do Oracle o suficiente para ajudar lá infelizmente.
Riyad Kalla 26/03
4

A chamada de inserção de caminho direto com a dica de acréscimo faz com que um bloqueio exclusivo seja executado em toda a tabela, portanto, ter vários encadeamentos executando a inserção não ajudará. Você precisaria endereçar explicitamente uma partição diferente a cada inserção ...

insert /*+ append */ into my_table partition (partition_name_1) ...

... para obter bloqueios exclusivos no nível da partição. Você não poderá fazer isso com uma tabela particionada na data de inserção, provavelmente, mas poderá usar o particionamento composto (não o subpartição) para obter várias partições por intervalo exclusivo de datas de inserção.

Não confirme no meio das inserções, apenas no final.

David Aldridge
fonte
Preciso mencionar o nome da partição na consulta explicitamente? Eu tenho coluna, tipo de tipo de evento. Vou tentar particionar por grupo de eventos e fazer com que cada thread insira lotes de linhas apenas de um tipo específico
adrift
Para evitar um bloqueio exclusivo no nível da tabela, sim.
David Aldridge
A dica APPEND deve ser ignorada pelo Oracle para inserções de linha única. A descrição do processo pelo OP parece implicar inserções de linha única em lote. Não tenho certeza de como eles são tratados. Eu acho que não APPEND, mas ele precisa de alguns testes.
Vincent Malgrat
Hmmm, não considerou isso - é ainda pior, se sim.
David Aldridge
Vale a pena tentar inserções com várias linhas com a dica APPEND? Em seguida, quantas entradas por inserção de várias linhas devo enviar?
à deriva