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 / 332029
Accepted
Bear Bile Farming is Torture
Bear Bile Farming is Torture
Asked: 2023-10-11 13:47:00 +0800 CST2023-10-11 13:47:00 +0800 CST 2023-10-11 13:47:00 +0800 CST

A eficácia do índice composto onde o prefixo é contínuo/alta cardinalidade

  • 772

esquema:

{
  time_utc: "milliseconds",
  city: "string",
  age: "integer"
}

índice:

{
  time_utc: 1,
  city: 1,
  age: 1
}

consulta de exemplo:

col.aggregate([
  {
    $match: { time_utc: { $exists: true }  city: "new york", age: { $gt: 18 } }
  },
  {
    $sort: { time_utc: -1 }
  }
])

Tenho certeza que o índice composto será utilizado nesta consulta, para que a classificação seja eficiente.

No entanto, a $matchetapa /filtragem de documentos não parece eficiente porque podemos assumir que time_utcé única em toda a coleção.

Suponhamos que haja 1 milhão de documentos no acervo e apenas 10 serão devolvidos. Suponhamos ainda que os 10 documentos estejam localizados na parte inferior da time_utcclassificação.

Neste cenário, a consulta deve varrer todo o valor de 1 milhão do índice para descobrir os 10 documentos. Isso equivale a uma varredura completa da coleção.

Vamos supor o contrário, que existam apenas 2 valores únicos em time_utc. Neste cenário, parece que o índice para os campos citye agepode de fato ser eficaz.

Meu raciocínio está correto?

index
  • 2 2 respostas
  • 27 Views

2 respostas

  • Voted
  1. Best Answer
    user20042973
    2023-10-17T00:35:22+08:002023-10-17T00:35:22+08:00

    Eu diria que parte do seu raciocínio está correto e que pensar nas consequências da estrutura do índice é de fato extremamente importante. Como sempre, @Wernfried Domscheit destaca alguns pontos importantes em sua resposta . Mas acho que há mais para desvendar aqui, então vamos nos aprofundar. Começaremos respondendo diretamente a algumas das afirmações.

    Tenho certeza que o índice composto será utilizado nesta consulta, para que a classificação seja eficiente.

    O índice pode ser usado, sim. Mas, como mencionei antes , isso não significa que será usado. Isto é particularmente verdadeiro na presença de outros índices viáveis, dos quais falaremos mais tarde.

    ... podemos assumir que time_utcé único em toda a coleção.

    Suponhamos que haja 1 milhão de documentos no acervo e apenas 10 serão devolvidos. Suponhamos ainda que os 10 documentos estejam localizados na parte inferior da time_utcclassificação.

    Neste cenário, a consulta deve varrer todo o valor de 1 milhão do índice para descobrir os 10 documentos.

    Certo. O comportamento/problema que você descreveu não está isolado no local onde os resultados estão localizados durante a verificação do índice.

    No cenário que você descreveu, a varredura de índice necessária é muito 'ampla'. Isso o torna bastante ineficiente no atendimento da consulta. A colocação dos resultados nesse índice é irrelevante para o comportamento e desempenho da consulta em geral. Sua consulta levaria o mesmo tempo e faria a mesma quantidade de trabalho se esses 10 documentos também fossem os primeiros 10 na digitalização do índice.

    Podemos ver isso visualizando as estatísticas de execução do explainplano ao emitir a classificação nas duas direções, uma vez que o índice pode ser verificado na direção forwardou . reverseUsando a classificação decrescente fornecida na pergunta:

    > db.foo.aggregate([ { $match: { time_utc: { $exists: true }, city: "new york", age: { $gt: 18 } } }, { $sort: { time_utc: -1 } }]).explain("executionStats").executionStats
    {
      nReturned: 10,
      totalKeysExamined: 1000000,
      totalDocsExamined: 10,
      ...
          keyPattern: { time_utc: 1, city: 1, age: 1 },
          direction: 'backward',
    

    E usando o oposto (ascendente):

    > db.foo.aggregate([ { $match: { time_utc: { $exists: true }, city: "new york", age: { $gt: 18 } } }, { $sort: { time_utc: 1 } }]).explain("executionStats").executionStats
    {
      nReturned: 10,
      totalKeysExamined: 1000000,
      totalDocsExamined: 10,
      ...
          keyPattern: { time_utc: 1, city: 1, age: 1 },
          direction: 'forward',
    

    Vamos supor o contrário, que existam apenas 2 valores únicos em time_utc. Neste cenário, parece que o índice para os campos citye agepode de fato ser eficaz.

    Sim. Como você deixou implícito aqui, isso é uma consequência da distribuição dos dados, em oposição a algum comportamento diferente do banco de dados nesta situação.

    Usando a terminologia acima, os limites para a varredura do índice ainda são tão “amplos” quanto eram antes. A diferença aqui é que a ‘largura’ do índice é muito menor. Nesta situação em que existem 2 valores únicos, esperaria explainque a saída (provavelmente) reportasse apenas alguns, seekso que refletiria a estrutura lógica do índice sendo 'mais estreita' a este respeito.

    Vamos explorar isso um pouco mais.

    Varredura 'ampla'

    Em geral, quando a definição do índice leva ao(s) campo(s) de classificação, a varredura do índice nesse campo não será limitada. No seu caso, você tem uma condição predicada no mesmo campo ( time_utc), mas na verdade isso não resulta no estreitamento da varredura. Podemos ver isso na explainsaída:

    > db.foo.aggregate([ { $match: { time_utc: { $exists: true }, city: "new york", age: { $gt: 18 } } }, { $sort: { time_utc: -1 } }]).explain().queryPlanner.winningPlan.inputStage.indexBounds
    {
      time_utc: [ '[MaxKey, MinKey]' ],
      city: [ '["new york", "new york"]' ],
      age: [ '[inf.0, 18)' ]
    }
    

    Esses limites são os mesmos, independentemente dos dados da coleção.

    Agora, se olharmos as estatísticas de execução do IXSCANconjunto de dados original (1 milhão de valores únicos), podemos ver que o banco de dados precisa percorrer o índice para encontrar a seção relevante e acaba olhando para tudo:

    > db.foo.aggregate([{$group:{_id:'$time_utc'}},{$count:'uniqueTimes'}])
    [ { uniqueTimes: 1000000 } ]
    > db.foo.aggregate([ { $match: { time_utc: { $exists: true }, city: "new york", age: { $gt: 18 } } }, { $sort: { time_utc: -1 } }]).explain("executionStats").executionStats.executionStages.inputStage
    {
      keyPattern: { time_utc: 1, city: 1, age: 1 },
      keysExamined: 1000000,
      seeks: 999991,
      ...
    

    Mas quando há apenas 2 valores distintos para a chave principal definida pelo índice, o banco de dados consegue ignorar a maior parte dela:

    > db.foo.aggregate([{$group:{_id:'$time_utc'}},{$count:'uniqueTimes'}])
    [ { uniqueTimes: 2 } ]
    > db.foo.aggregate([ { $match: { time_utc: { $exists: true }, city: "new york", age: { $gt: 18 } } }, { $sort: { time_utc: -1 } }]).explain("executionStats").executionStats.executionStages.inputStage
    {
      keyPattern: { time_utc: 1, city: 1, age: 1 },
      keysExamined: 12,
      seeks: 3,
      ...
    

    Recomendações (Orientação ESR)

    Como a outra resposta menciona, se os conjuntos de resultados forem pequenos, o custo da classificação não será particularmente alto.

    Em geral, porém, o MongoDB sugere que o ponto de partida para a indexação é o que eles chamam de Regra ESR . Usando esta abordagem, o predicado on cityé uma condição de igualdade, portanto deve ser colocado em primeiro lugar no índice. O time_utcpredicado, entretanto, é uma condição de intervalo , pois basicamente significa "qualquer valor, exceto o ausente". Como esse campo é usado em ambos os aspectos (classificação e intervalo), o índice que as diretrizes sugerem que você tente é:

    {
      city: 1,
      time_utc: 1,
      age: 1
    }
    

    Agora, voltando ao ponto sobre o tamanho do conjunto de resultados, é definitivamente possível que você possa realmente ver um melhor desempenho trocando a segunda e a terceira chaves e incorrendo na classificação de bloqueio:

    {
      city: 1,
      age: 1,
      time_utc: 1
    }
    

    Isso depende inteiramente da seletividade dos dados e pode ser que alguns valores de predicado funcionem melhor com um índice do que com outro. Você teria que testar e avaliar em seu próprio ambiente.

    • 1
  2. Wernfried Domscheit
    2023-10-11T17:15:38+08:002023-10-11T17:15:38+08:00

    Primeiro, os valores de data/hora devem ser melhor armazenados adequadamente como Dateobjetos, não como números ou - pior ainda - como strings. Dateos objetos são sempre horários UTC, portanto, devem atender aos seus requisitos.

    Se a condição on citye ageretornar apenas 10 documentos, você não precisará de um índice em time_utc. Para ordenação de 10 documentos não importa se utiliza índice ou não, independentemente de time_utcpossuir 10 milhões de valores distintos ou apenas dois valores distintos.

    • 0

relate perguntas

  • Como criar várias entradas no índice com base nos campos de uma linha?

  • Quando devo usar uma restrição exclusiva em vez de um índice exclusivo?

  • Quanto "Padding" coloco em meus índices?

  • O que significa "índice" em RDBMSs? [fechado]

  • Como criar um índice condicional no MySQL?

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