Consultas otimizadas com campos fragmentados

Nesta página, descrevemos como ver e controlar o uso de campos fragmentados no Firestore. Esse recurso está disponível na edição Enterprise do Firestore.

Quando os documentos são gravados, o Firestore pode determinar que campos específicos precisam ser armazenados em um formato fragmentado. Os campos fragmentados otimizam o desempenho da consulta lendo apenas os campos necessários, e não o documento completo.

Consultas que se beneficiam de campos fragmentados

As leituras em campos fragmentados são aplicadas às seguintes formas de consulta, quando aplicável:

  • Consultas de agregação: consultas que só precisam acessar um subconjunto de campos para operações de agregação. Exemplo:

    db.pipeline()
      .collection("/customers")
      .where(lessThan("account_balance", 0))
      .aggregate(
        countAll().as("total"),
      )
    

    ou com "group-by":

    db.pipeline()
      .collection("/customers")
      .where(lessThan("account_balance", 0))
      .aggregate({
        accumulators: [
          field('account_balance').average().as('avg_account_balance')
        ],
        groups: [field('market_segment')]
      })
    
  • Consultas de projeção: consultas que retornam apenas um subconjunto específico de campos. Exemplo:

    db.pipeline()
      .collection("/customers")
      .select("family_name", "given_name")
      .limit(10)
    
  • Consultas de filtro: consultas em que o mecanismo de consulta do Firestore determina que o uso de campos fragmentados para filtragem de documentos é benéfico. Exemplo:

    db.pipeline()
      .collection("/customers")
      .where(equal("given_name", "alice"))
    

Ver o uso de campos fragmentados

Use o Query Explain para verificar se uma consulta usa campos fragmentados. O nó TableScan no plano de consulta inclui uma seção Storage com as seguintes métricas:

  • Forma da verificação:
    • shredded_fields_only: a consulta lê apenas campos fragmentados.
    • shredded_fields_backjoin: a consulta lê campos fragmentados e faz junção com o documento original para outros campos.
  • Campos fragmentados usados: uma lista de nomes de campos lidos como campos fragmentados.
  • Recheck count: um mapa de contadores para novas verificações. Uma nova verificação significa voltar a ler o documento completo original ao verificar os campos fragmentados. Isso pode acontecer se o valor do campo em um documento exceder 8 KiB, o que é muito grande para o armazenamento de campos fragmentados.

Exemplo de saída

...
└── • TableScan
        source: /customers
        order: UNDEFINED
        row range: (-∞..+∞)
        filter: ($account_balance_1 < 0L)
        output bindings: {$account_balance_1=account_balance, $market_segment_1=market_segment}
        variables: [$account_balance_1, $market_segment_1]

        Execution:
         records returned: 1,374
         latency: 26.58 ms
         post-filtered rows: 13,626
         records scanned: 15,000
         data bytes read: 23.73 MiB (24,887,141 B)

        Storage:
         scan shape: shredded_fields_only
         shredded fields used: [account_balance, market_segment]

Controlar o uso de campos fragmentados

Por padrão, o Firestore usa campos fragmentados quando disponíveis. É possível controlar esse comportamento usando a opção de consulta table_scan_method.

Valores aceitos para a opção table_scan_method:

  • shredded_fields_enabled (padrão): use campos fragmentados quando disponíveis.
  • shredded_fields_disabled: não use campos fragmentados.
  • force_shredded_fields: falha na consulta se uma verificação de tabela não puder ser concluída com a leitura de campos fragmentados.

Exemplo

var opts = new PipelineExecuteOptions()
    .with("table_scan_method", "shredded_fields_disabled");

var snapshot = db.pipeline()
    .collection("/customers")
    .where(equal("given_name", "alice"))
    .execute(opts)
    .get();

Avisos de desempenho da consulta

O Firestore pode emitir avisos de performance no resultado do Query Explain quando é detectado um uso ineficiente de campos fragmentados. Exemplo:

  • Consultas de baixa seletividade: ocorrem quando uma consulta verifica campos fragmentados para filtragem, mas filtra poucos documentos, tornando a verificação ineficiente.

  • Consultas de alta verificação: ocorrem quando a consulta volta a leituras completas de documentos com frequência, o que pode afetar a performance. Use funções como storage_size para identificar valores grandes que acionam novas verificações.

Nesses casos, considere desativar as leituras de campos fragmentados usando opções de consulta.

Limitações

O Firestore só destrói campos de nível superior. Ele também restringe o número de campos que podem ser fragmentados por grupo de coleções.