Otimizador baseado em custo

O Spark SQL pode usar um otimizador baseado em custo (CBO) para melhorar os planos de consulta. Isso é especialmente útil para consultas com várias junções. Para que isso funcione, é essencial coletar estatísticas de tabela e coluna e mantê-las atualizadas.

Coletar estatísticas

Para obter o benefício completo do CBO, é importante coletar estatísticas de coluna e estatísticas de tabela. Você pode usar o ANALYZE TABLE comando para coletar estatísticas manualmente.

Dica

Para manter as estatísticas atualizadas, execute ANALYZE TABLE depois de gravar na tabela.

Use ANALYZE.

A otimização preditiva executa automaticamente ANALYZE, um comando para coletar estatísticas, em tabelas gerenciadas do Catálogo do Unity. O Databricks recomenda habilitar a otimização preditiva para todas as tabelas gerenciadas do Catálogo do Unity para simplificar a manutenção de dados e reduzir os custos de armazenamento. Veja ANALYZE TABLE ... ESTATÍSTICAS DE COMPUTAÇÃO.

Você pode remover estatísticas do otimizador para que o otimizador não dependa mais delas, por exemplo, para atenuar um problema de planejamento causado pelas estatísticas. Veja ANALYZE TABLE ... DROP STATISTICS.

Verificar planos de consulta

Há várias maneiras de verificar o plano de consulta.

EXPLAIN comando

Para verificar se o plano usa estatísticas, use o comando EXPLAINSQL.

Se as estatísticas estão ausentes, o plano de consulta pode não ser ideal.

== Optimized Logical Plan ==
Aggregate [s_store_sk], [s_store_sk, count(1) AS count(1)L], Statistics(sizeInBytes=20.0 B, rowCount=1, hints=none)
+- Project [s_store_sk], Statistics(sizeInBytes=18.5 MB, rowCount=1.62E+6, hints=none)
   +- Join Inner, (d_date_sk = ss_sold_date_sk), Statistics(sizeInBytes=30.8 MB, rowCount=1.62E+6, hints=none)
      :- Project [ss_sold_date_sk, s_store_sk], Statistics(sizeInBytes=39.1 GB, rowCount=2.63E+9, hints=none)
      :  +- Join Inner, (s_store_sk = ss_store_sk), Statistics(sizeInBytes=48.9 GB, rowCount=2.63E+9, hints=none)
      :     :- Project [ss_store_sk, ss_sold_date_sk], Statistics(sizeInBytes=39.1 GB, rowCount=2.63E+9, hints=none)
      :     :  +- Filter (isnotnull(ss_store_sk) && isnotnull(ss_sold_date_sk)), Statistics(sizeInBytes=39.1 GB, rowCount=2.63E+9, hints=none)
      :     :     +- Relation[ss_store_sk,ss_sold_date_sk] parquet, Statistics(sizeInBytes=134.6 GB, rowCount=2.88E+9, hints=none)
      :     +- Project [s_store_sk], Statistics(sizeInBytes=11.7 KB, rowCount=1.00E+3, hints=none)
      :        +- Filter isnotnull(s_store_sk), Statistics(sizeInBytes=11.7 KB, rowCount=1.00E+3, hints=none)
      :           +- Relation[s_store_sk] parquet, Statistics(sizeInBytes=88.0 KB, rowCount=1.00E+3, hints=none)
      +- Project [d_date_sk], Statistics(sizeInBytes=12.0 B, rowCount=1, hints=none)
         +- Filter ((((isnotnull(d_year) && isnotnull(d_date)) && (d_year = 2000)) && (d_date = 2000-12-31)) && isnotnull(d_date_sk)), Statistics(sizeInBytes=38.0 B, rowCount=1, hints=none)
            +- Relation[d_date_sk,d_date,d_year] parquet, Statistics(sizeInBytes=1786.7 KB, rowCount=7.30E+4, hints=none)

Importante

A estatística rowCount é especialmente importante para consultas com várias junções. Se rowCount estiver ausente, isso significa que não há informações suficientes para calculá-la (ou seja, algumas colunas necessárias não têm estatísticas).

No Databricks Runtime 16.0 e superior, a saída do EXPLAIN comando lista as tabelas referenciadas que têm estatísticas ausentes, parciais e completas, como na saída de exemplo a seguir:

== Optimizer Statistics (table names per statistics state) ==
  missing = date_dim, store
  partial =
  full    = store_sales
Corrective actions: consider running the following command on all tables with missing or partial statistics
  ANALYZE TABLE <table-name> COMPUTE STATISTICS FOR ALL COLUMNS

Interface do usuário do Spark SQL

Use a página interface do usuário do SQL do Spark para ver o plano executado e a precisão das estatísticas.

Estimativa ausente

Uma linha como rows output: 2,451,005 est: N/A indica que esse operador produz cerca de 2M de linhas e não havia estatísticas disponíveis.

Estimativa boa

Uma linha como rows output: 2,451,005 est: 1616404 (1X) significa que esse operador produz aproximadamente 2 milhões de linhas, enquanto a estimativa era de aproximadamente 1,6 M e o fator de erro de estimativa era 1.

Estimativa ruim

Uma linha como rows output: 2,451,005 est: 2626656323 significa que esse operador produz aproximadamente 2 milhões de linhas enquanto a estimativa era de 2B linhas, portanto, o fator de erro de estimativa era 1000.

Desabilitar o otimizador baseado em custo

O CBO está habilitado por padrão. Você desativa o CBO alterando o sinalizador spark.sql.cbo.enabled.

spark.conf.set("spark.sql.cbo.enabled", false)