{# Spec 151 - per-table layout recommendation detail. Renders: - Header (table name, region, size, window cost) - Current vs proposed layout (side-by-side) - Ranked candidate columns (table) - Apply SQL (copy panel) - Rollback SQL (copy panel) - Caveats list Empty state (no recommendation in latest scan) renders a single explanation card with a "Re-run scan" link instead of 404ing. #} {% extends "layout.html" %} {% block content %} {% from "components/_page_header.html" import back_link, header_card %} {# Spec 151 US3 - small "Deep analyse" entry point per candidate column. Renders as either a cached-result chip (when the user has already run deep analysis on that column) or a tiny form button that POSTs to the /deep/preview endpoint to get a cost estimate before the chargeable run. The route accepts ``column_name`` as form data; the table_full_name is on the URL. #} {%- macro _deep_button(table_full_name, column_name, deep_results_by_column) -%} {%- set _deep = (deep_results_by_column or {}).get(column_name) -%} {%- if _deep -%} ~{{ "{:,}".format(_deep.approx_distinct_count or 0) }} distinct {%- else -%}
{%- endif -%} {%- endmacro %}{% if _dataset %}{{ _dataset }}.{% endif %}{{ _table }}{% endset %}
{{ header_card(_title, caption="Partition & Cluster recommendation") }}
{# Recommendation source / provenance - make it unmistakable whether
this pick comes from Governor-audit, BigQuery's own Recommender, or
both (and whether the two methodologies agree). #}
{% if recommendation %}
{% set _src_has_audit_pick = recommendation.recommended_partition_column or cluster_candidates %}
No recommendation in the latest scan for this table. The most common reasons:
Recommendations are derived from the workload the latest scan observed. Run another scan if you suspect this changed recently.
BigQuery's recommendation (second opinion)
{% if not _audit_has_pick %} BigQuery only - audit didn't analyze this table {% elif bq_second_opinion.agrees_with_audit_top_pick %} Agreement on top column {% else %} Different top pick {% endif %}BigQuery picks
{% if bq_second_opinion.bq_recommended_columns %}No specific columns surfaced
{% endif %}Methodology: BigQuery's ML-based recommender - slot-time + scan-pattern weighting on the recent workload.
Audit picks
{% if _audit_has_pick %}Methodology: cost-weighted filter / join / group-by frequency across {{ recommendation.contributing_job_count }} cached queries.
{% else %}No audit pick - the table didn't meet the audit's size gates (≥ 10 GB cluster / ≥ 100 GB partition) or had too few consumer queries in the scan window to converge on a column. The audit's recommendations require both.
Methodology: cost-weighted filter / join / group-by frequency across cached consumer queries - needs a populated window to fire.
{% endif %}{{ bq_second_opinion.bq_description }}
{% endif %}BigQuery second opinion
Add roles/recommender.bigqueryPartitionClusterViewer to the principal that runs the scan to surface BigQuery's own recommendation alongside the audit's. The page works without it - this enables a second-opinion panel that increases confidence when both methodologies agree.
Why this recommendation
{% if _issue_consumers | length > 0 %}
{{ _issue_consumers | length }} downstream model{{ 's' if _issue_consumers | length != 1 else '' }} reading from this table carr{{ 'y' if _issue_consumers | length != 1 else 'ies' }} active issues today.
{% if _cluster_pick %}
Clustering by {{ _cluster_pick.column_name }} reorders the table's micro-files so reads filtered on it scan fewer bytes - the same scans that drive slot-contention and shuffle-spill on those downstreams. The lineage below names each impacted model (red).
{% elif _part_pick %}
Partitioning by {{ _part_pick.column_name }} lets BigQuery prune partitions at read time, reducing the byte volume that drives slot-contention and shuffle-spill on those downstreams.
{% endif %}
{% else %}
No downstream models with active issues today. The recommendation is preventative - it locks in efficient layout before issues appear at scale.
{% endif %}
Pick methodology: cost-weighted filter / join / group-by frequency across {{ recommendation.contributing_job_count }} cached consumer job{{ 's' if recommendation.contributing_job_count != 1 else '' }}, intersected with the table's schema. Columns must clear the materiality (≥ 1 GB), partition (DATE / TIMESTAMP, 70 % filter), and cluster (50 % combined) gates.
Downstream lineage (all consumers)
Every consumer model that reads from this table. Red carries active issues, blue is clean. Click a chip to open its detail.
+ {{ _hidden_count }} more downstream model{{ 's' if _hidden_count != 1 else '' }} - view all
{% endif %} {% endif %}Caveats