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 / 321514
Accepted
Nuno
Nuno
Asked: 2022-12-29 16:47:10 +0800 CST2022-12-29 16:47:10 +0800 CST 2022-12-29 16:47:10 +0800 CST

No MySQL/MariaDB, o desempenho dos índices diminui à medida que eles se tornam cada vez maiores?

  • 772

No momento, estou explorando o uso de PARTITION, para um caso de uso específico que tenho.
Eu uso InnoDB, arquivo por tabela. MariaDB 10.8.

Eu estava lendo a página Manutenção de PARTIÇÃO no MySQL de Rick .

Gostaria de destacar este trecho:

WHERE X = 1234-- Isso permite que a "remoção de partição" olhe apenas naquela partição. Mas isso não é melhor do que INDEX(x)em uma tabela não particionada. E você provavelmente precisará desse índice de qualquer maneira; após a primeira 'remoção' até a partição desejada, você ainda precisa do índice. Não mais rápido.
Uma falácia comum: "O particionamento fará com que minhas consultas sejam executadas mais rapidamente". Não vai. Pondere o que é necessário para uma 'consulta pontual'. Sem particionamento, mas com um índice apropriado, há um BTree (o índice) para detalhar para encontrar a linha desejada. Para um bilhão de linhas, isso pode ter 5 níveis de profundidade. Com o particionamento, primeiro a partição é escolhida e "aberta", então uma BTree menor (de, digamos, 4 níveis) é detalhada. Bem, a economia do BTree mais raso é consumida ao abrir a partição. Da mesma forma, se você observar os blocos de disco que precisam ser tocados e quais deles provavelmente serão armazenados em cache, chegará à conclusão de que é provável o mesmo número de acertos de disco. Como as ocorrências de disco são o principal custo em uma consulta, o particionamento não ganha nenhum desempenho (pelo menos para este caso típico).

Eu entendo perfeitamente o que isso significa, mas eu tenho uma pergunta:

No MySQL/MariaDB, o desempenho dos índices diminui à medida que eles se tornam cada vez maiores?

Para um bilhão de linhas, ou para 100 bilhões de linhas, um bom índice é sempre melhor do que partições, em termos de desempenho?

--

Há também este bit que está mais próximo do que estou tentando beneficiar:

Caso de uso nº 3 -- Ponto de acesso. Isso é meio complicado de explicar. Dada esta combinação:
⚈ O índice de uma tabela é muito grande para ser armazenado em cache, mas o índice para uma partição pode ser armazenado em cache e
⚈ O índice é acessado aleatoriamente e
⚈ A ingestão de dados normalmente seria limitada por E/S devido à atualização do índice O
particionamento pode mantenha todo o índice "quente" na RAM, evitando assim muitas E/S.

A grande vitória do Caso nº 3: Melhorar o armazenamento em cache para diminuir a E/S para acelerar as operações.

O "índice em cache" também é válido para o InnoDB? Meu entendimento se CACHE INDEXaplica apenas ao MyISAM.
Ou isso está relacionado ao fato de estar no InnoDB Buffer Pool?

E em relação à diminuição de I/O, isso se aplica a servidores NVMe? My %iowaité 0,00, enquanto meu aplicativo é de gravação intensiva.

mysql
  • 3 3 respostas
  • 1426 Views

3 respostas

  • Voted
  1. Bill Karwin
    2022-12-29T17:36:24+08:002022-12-29T17:36:24+08:00

    Para um bilhão de linhas, ou para 100 bilhões de linhas, um bom índice é sempre melhor do que partições, em termos de desempenho?

    Há várias coisas que posso dizer sobre isso.

    • Não podemos fazer essa generalização, pois depende da consulta. Em geral, todo tipo de otimização é uma grande ajuda para o tipo certo de consulta, em detrimento de outros tipos de consulta. Portanto, você deve ser muito específico sobre qual consulta deseja otimizar antes de escolher o método de otimização.

    • Não é uma escolha ou um ou outro. Você pode particionar uma tabela e também definir um índice, para que as pesquisas sejam otimizadas em uma determinada partição.

    • Não acho que você tenha 100 bilhões de linhas. Se o fizesse, você não estaria fazendo esta pergunta no Stack Exchange, você estaria atribuindo à sua equipe de arquitetos de banco de dados em tempo integral a tarefa de otimizá-lo. Sem dúvida, eles voltariam com um design que usa muitos servidores. É impraticável armazenar 100 bilhões de linhas em uma única tabela. Como você faria o backup? Como você adicionaria uma coluna?

    O InnoDB usa índices de árvore B (também de texto completo e índices espaciais, mas para esta discussão assumimos o tipo padrão de índice).

    Índices de árvore B têm complexidade O(log 2 n ) tanto para inserção quanto para pesquisa, onde n é o número de entradas na estrutura de dados. Inserir ou pesquisar, portanto, fica mais caro à medida que o índice aumenta.

    A E/S exigida por uma pesquisa de índice é uma função da profundidade da árvore B. Ou seja, quantos níveis de nós não terminais devem ser percorridos para chegar ao nó folha. A profundidade depende de quantas entradas de índice existem e também de quão grande é o tipo de dados de uma determinada entrada, porque os tamanhos de página do InnoDB são fixos, portanto, apenas alguns nós de índice podem caber em uma página. Veja: https://www.percona.com/blog/2009/04/28/the_depth_of_a_b_tree/

    O custo de E/S pode ser mitigado mantendo subconjuntos das páginas de índice na RAM, no buffer pool do InnoDB. Mas se o índice crescer muito mais do que a RAM, não haverá buffer pool suficiente para manter todo o índice, portanto, se você fizer pesquisas aleatoriamente em todo o índice, o InnoDB provavelmente removerá as páginas que você precisará novamente em breve. Essas páginas serão recarregadas do armazenamento quando você precisar delas, mas isso pode levar a uma sobrecarga extra, pois as páginas são trocadas dentro e fora da RAM.

    Os índices de cache só se aplicam ao MyISAM. O InnoDB armazena em cache as páginas sob demanda, que podem incluir um subconjunto de um determinado índice. Esqueça qualquer comando manual para carregar índices no cache. Para ser sincero, recomendo esquecer o MyISAM para qualquer finalidade. Não o vejo usado adequadamente desde os anos 2000.

    Você perguntou sobre o armazenamento NVMe. O NVMe é obviamente mais rápido que as interfaces SATA antigas, mas como ele se compara à RAM? Depende do que você mede, mas tanto para o tempo de acesso quanto para a taxa de transferência (MB/segundo), você pode contar com uma RAM várias vezes mais rápida que a última geração de NVMe. Além disso, o código InnoDB foi escrito para assumir que as páginas devem estar na RAM antes de serem lidas. Ainda é uma vitória manter os dados e as páginas de índice em cache na RAM.

    Concordo com a afirmação geral de Rick de que o particionamento geralmente não ajudará no desempenho tanto quanto você pensa. É útil no cenário certo, mas não é uma solução mágica "tudo vai rápido". Isso também vale para qualquer outro tipo de otimização!

    • 10
  2. Best Answer
    Rick James
    2022-12-29T21:04:12+08:002022-12-29T21:04:12+08:00

    (Além dos comentários de Bill...)

    Outra forma de analisar o desempenho -- "Contar as ocorrências do disco".

    • O InnoDB armazena em cache blocos de 16 KB (dados e índice) em seu buffer_pool.
    • O cache é sob demanda e é o menos usado recentemente.
    • Todas as atividades (leitura, gravação, pesquisa etc.) são feitas no buffer_pool, não diretamente no disco.
    • Uma regra simples é que o fanout de qualquer InnoDB BTree é de cerca de 100. (Percona usou 128 - essencialmente o mesmo). Um bilhão de linhas (de dados ou índice) terá 5 níveis. Isso significa que 5 blocos devem ser buscados (se ainda não estiverem em cache) para fazer uma consulta de ponto simples. Ou 10 blocos para uma pesquisa por meio de uma chave secundária. (6 e 12 para 100 bilhões de linhas.)
    • Se você estiver buscando 101 linhas 'consecutivas' desse BTree, precisará de 2 nós folha (aquele com o qual você começa mais o próximo). Outra regra prática: todos os nós não folha provavelmente são armazenados em cache.
    • Se sua atividade for aleatória (como com um UUID ou hash para o PK) e o buffer_pool não puder conter todo o BTree, o cache se tornará praticamente inútil. Isso faz com que cada consulta de ponto leve pelo menos 1 hit de disco. Nesse caso, "muito grande é péssimo para o desempenho".
    • Se, por outro lado, você estiver apenas tocando nas linhas "recentes" (e o PK for AUTO_INCREMENT ou baseado em tempo), o cache buffer_pool terá os dados desejados 99 vezes em 100. Ou seja, não há degradação, pois o tabela cresce, mesmo quando muito maior que o buffer_pool.

    (Eu fiz muitos 'acenos de mão' nessas duas últimas declarações.)

    Espero ter lhe dado algumas pistas sobre como julgar por si mesmo se sua mesa sofrerá ou não com o crescimento. Se você quiser uma discussão mais aprofundada, forneça o arquivo CREATE TABLE. Quando alguém fala sobre tabelas de bilhões de linhas, gosto de reduzir os tipos de dados, reestruturar o esquema, normalizar, adicionar tabelas de resumo, considerar o sharding etc. Mas raramente recomendo o particionamento. Às vezes, recomendo "manter as tabelas de resumo, mas jogar fora a tabela de fatos". Isso elimina todos os tipos de problemas de dimensionamento e desempenho.

    • 9
  3. bobflux
    2022-12-30T04:45:29+08:002022-12-30T04:45:29+08:00

    No MySQL/MariaDB, o desempenho dos índices diminui à medida que eles se tornam cada vez maiores?

    Depende do que você entende por "desempenho"...

    Se você quer dizer "encontrar uma linha ou um intervalo de linhas com base na chave indexada", a resposta seria "um pouco". Como os outros explicaram, desde que o conjunto de trabalho do índice permaneça no cache, "grande" pode ficar um pouco mais lento que "pequeno", mas é provável que seja inundado pelo restante do tempo de consulta usado por logística, rede , análise, etc. Se as páginas de folha não forem armazenadas em cache, isso adicionaria um IO aleatório, então você teria que perguntar ao seu sistema IO sobre quanto tempo isso levará.

    Mas você pergunta sobre índice versus particionamento, portanto, neste caso, se os dados forem os mesmos no caso "particionado" e no caso "tabela única", o tamanho total dos índices nas partições seria praticamente o mesmo que o índice na mesa única. Com a mesma carga de consulta, não há motivo para que um seja armazenado em cache melhor que o outro, portanto, provavelmente não haveria diferença entre os dois. Se você acessar apenas as linhas mais recentes, ambos os cenários se beneficiariam da mesma forma por precisar armazenar em cache apenas as partes correspondentes dos índices.

    No entanto, se você tiver uma visão global do desempenho e adicionar coisas como "excluir todas as linhas com mais de 12 meses" e tiver um bilhão de linhas para excluir ao executar esta operação de arquivamento, tabelas e índices enormes se tornarão uma ideia extremamente ruim (TM ). Se for um índice na data, talvez seja tolerável porque a exclusão atingirá um pedaço contíguo dele. No entanto, se for um índice em uma coluna bastante aleatória, cada linha excluída acionará gravações aleatórias em algum lugar do índice, em todo o lugar, e isso será interrompido para sempre.

    Considerando que, se você usar o particionamento, "DROP PARTITION" é quase instantâneo porque, nos bastidores, está apenas excluindo os arquivos correspondentes. A menos que haja gatilhos ON DELETE a serem acionados, não há sentido em ler as linhas a serem excluídas se o banco de dados souber que estamos descartando toda a partição.

    Se não houver gravações em partições mais antigas, isso pode tornar os backups muito mais rápidos, se a ferramenta de backup puder explorar o fato de que não há necessidade de fazer backup de uma partição que não foi alterada.

    Estou editando para adicionar outras circunstâncias em que o particionamento pode tornar suas consultas mais rápidas:

    Você não tem dinheiro suficiente para colocar toda a tabela em um SSD, então você coloca as partições antigas (e índices) que raramente são acessadas em um RAID desajeitado e lento, e as partições mais recentes (e índices) que veem a maior parte a ação em alguns SSDs extremamente rápidos. Essa é uma boa otimização "dinheiro versus desempenho", mas você terá que mover as partições de vez em quando. Talvez você possa até replicar apenas as partições recentes ou colocar uma partição por servidor e executá-las em paralelo, se o banco de dados suportar, coisas assim.

    Além disso, se o otimizador de consulta estragar tudo e decidir fazer uma verificação completa da tabela ou algo do tipo, talvez se sua tabela for particionada e a consulta tiver uma condição na chave de partição, o tamanho da confusão pode ser limitado a apenas um algumas partições em vez de toda a tabela.

    • 5

relate perguntas

  • Existem ferramentas de benchmarking do MySQL? [fechado]

  • Onde posso encontrar o log lento do mysql?

  • Como posso otimizar um mysqldump de um banco de dados grande?

  • Quando é o momento certo para usar o MariaDB em vez do MySQL e por quê?

  • Como um grupo pode rastrear alterações no esquema do banco de dados?

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