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)
/*+APPEND*/
dica é ignorada nas inserções de linha única (se você não precisaINSERT INTO ... SELECT
se preocupar em acrescentar). (3) Você deve configurar um exemplo do SQL * Loaderdirect=true
para estabelecer uma linha de base, conforme sugerido por @parsifal.Respostas:
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.
fonte
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 ...
... 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.
fonte