Per ottimizzare le prestazioni delle query del database AlloyDB per PostgreSQL, puoi ottimizzare le query SQL utilizzando insight basati sull'AI. Analizzando i piani di esecuzione delle query, la funzione ai.tune_sql, basata su un modello linguistico di grandi dimensioni (LLM), identifica i colli di bottiglia complessi e fornisce suggerimenti che puoi applicare per l'ottimizzazione.
Quando richiami la funzione ai.tune_sql, questa analizza la query e fornisce Query Insights e suggerimenti sulle query nelle seguenti aree:
- Riepilogo delle query: analizza i colli di bottiglia delle prestazioni delle query.
- Query rewrite: suggerisce tecniche di ottimizzazione per riscrivere la query originale in una query equivalente più efficiente.
- Suggerimenti per gli indici: suggerisce tipi di indici come indici su espressioni, indici GIN (Generalized Inverted Index) e indici ScaNN (Scalable Nearest Neighbors).
- Suggerimenti per la raccolta delle statistiche: suggerisce la raccolta di statistiche e tabelle
ANALYZEsu più colonne in base al piano di esecuzione delle query. - Ottimizzazione dei flag GUC (Grand Unified Configuration): consiglia nuovi valori GUC analizzando il piano di esecuzione e le informazioni di sistema, come l'utilizzo e le dimensioni della memoria e del buffer.
- Analisi e vacuum: consiglia di eseguire
ANALYZEeVACUUMsulle tabelle in base alla cronologia di analisi e vacuum e ai conteggi delle tuple attive e inattive.
Limitazioni
L'ottimizzazione delle query SQL presenta le seguenti limitazioni:
- Istruzioni preparate e parametrizzate: per le istruzioni preparate e parametrizzate,
ai.tune_sqlnon fornisce suggerimenti per la riscrittura delle query, anche se fornisce comunque altri suggerimenti per l'ottimizzazione. Per ricevere suggerimenti per la riscrittura delle query per una query che contiene segnaposto dei parametri, ad esempio$1o$2copiati da Query Insights opg_stat_statements, sostituisci i segnaposto con valori letterali rappresentativi prima di eseguireai.tune_sql. - Solo istruzioni
SELECTdi sola lettura quandoexplain_analyzeèTRUE: sono supportate solo singole istruzioniSELECTdi sola lettura quandoexplain_analyzeè impostato suTRUE. L'esecuzione diai.tune_sqlconexplain_analyzeimpostato suTRUEin altre istruzioni, comeINSERT,UPDATE,DELETE,SELECT INTOoSELECT FOR UPDATE, restituisce un messaggio di errore.
Prima di iniziare
Verifica di disporre di quanto segue:
- Un'istanza AlloyDB che esegue PostgreSQL 18 o versioni successive. Per saperne di più, consulta Crea un cluster e la relativa istanza principale.
- Un client
psqlconnesso alla tua istanza o accesso ad AlloyDB Studio. - Integrazione di Vertex AI abilitata.
- Versione 1.6.2 o successiva dell'estensione
google_ml_integrationinstallata, con le estensionigoogle_db_advisorehypopgabilitate. Per attivare l'estensionehypopg, cheai.tune_sqlutilizza per valutare e generare suggerimenti per gli indici, eseguiCREATE EXTENSION IF NOT EXISTS hypopg;.
Abilita l'ottimizzazione SQL
Registrare un LLM e abilitare i flag di database richiesti.
Crea un endpoint del modello Gemini per la funzione
ai.tune_sqlregistrando un endpoint del modello globale o un endpoint del modello regionale nella regione dell'istanza:Per registrare un endpoint del modello globale quando il modello non è disponibile nella regione dell'istanza, ad esempio
gemini-3.5-flashsulocations/global, esegui la seguente istruzione:CALL google_ml.create_model( model_id => 'gemini-3.5-flash-global', model_request_url => 'https://aiplatform.googleapis.com/v1/projects/PROJECT_ID/locations/global/publishers/google/models/gemini-3.5-flash:generateContent', model_qualified_name => 'gemini-3.5-flash', model_provider => 'google', model_type => 'llm', model_auth_type => 'alloydb_service_agent_iam');Sostituisci
PROJECT_IDcon l'ID del progetto in cui è disponibile il modello.Per registrare un endpoint del modello regionale nella regione dell'istanza, ad esempio
gemini-2.5-prosulocations/REGION_ID, esegui la seguente istruzione:CALL google_ml.create_model( model_id => 'gemini-2.5-pro', model_request_url => 'https://REGION_ID-aiplatform.googleapis.com/v1/projects/PROJECT_ID/locations/REGION_ID/publishers/google/models/gemini-2.5-pro:generateContent', model_qualified_name => 'gemini-2.5-pro', model_provider => 'google', model_type => 'llm', model_auth_type => 'alloydb_service_agent_iam');Sostituisci quanto segue:
REGION_ID: la regione dell'istanza AlloyDB, ad esempious-central1.PROJECT_ID: l'ID del progetto in cui è disponibile il modello.
Imposta l'ID modello per i suggerimenti di ottimizzazione delle query SQL nella sessione del database corrente. Specifica il
model_idche hai registrato nel passaggio precedente, ad esempio'gemini-3.5-flash-global'o'gemini-2.5-pro':SET google_db_advisor.llm_model_id = 'gemini-3.5-flash-global';Attiva l'ottimizzazione delle query SQL per la sessione del database corrente impostando il flag
google_db_advisor.enable_ai_tune_sql:SET google_db_advisor.enable_ai_tune_sql = on;Poiché
SETsi applica solo alla sessione di database corrente, puoi rendere persistenti queste impostazioni tra le sessioni eseguendoALTER DATABASE DATABASE_NAME SET FLAG_NAME = VALUE;per entrambi i flag o configurando i flag di database dell'istanza.
Ottimizza manualmente le query SQL
Per ottimizzare manualmente le query SQL, esegui la funzione ai.tune_sql utilizzando un'istruzione SELECT.
Connetti un client
psqla un'istanza AlloyDB o apri AlloyDB Studio.Se hai utilizzato
SETper configuraregoogle_db_advisor.llm_model_idegoogle_db_advisor.enable_ai_tune_sql, esegui queste istruzioniSETnella stessa sessione del database prima di chiamareai.tune_sql.Per ottimizzare le query SQL, esegui la funzione
ai.tune_sql. Questa funzione recupera lo schema relativo alla query e lo invia, insieme alla query, all'LLM per l'analisi delle prestazioni:SELECT ai.tune_sql(query => 'SQL_QUERY', explain_analyze => TRUE);Sostituisci
SQL_QUERYcon la query SQL che vuoi analizzare.Per impostazione predefinita, il parametro di esecuzione (
explain_analyze) è impostato suTRUE. Se impostata suTRUE, la funzione esegueEXPLAIN ANALYZEper eseguire la query e acquisire il piano di esecuzione. Questo approccio fornisce suggerimenti per l'ottimizzazione delle query più accurati e utili. Se impostiexplain_analyzesuFALSE, la funzione esegue soloEXPLAINper generare un piano senza eseguire la query.
Visualizza i piani di query con i suggerimenti per il rendimento
L'output mostra prima il piano di query standard, seguito dai consigli dettagliati generati dall'AI. I suggerimenti includono un riepilogo delle query, riscritture suggerite e suggerimenti per la raccolta di statistiche, l'ottimizzazione dei flag GUC e il vacuuming. La funzione ai.tune_sql può richiedere da due a quattro minuti per generare i suggerimenti.
L'esempio seguente mostra l'output ai.tune_sql per una query anti-join:
SELECT ai.tune_sql(
'SELECT *
FROM store_sales
WHERE ss_customer_sk NOT IN (
SELECT sr_customer_sk
FROM store_returns
WHERE sr_item_sk = ss_item_sk)');
tune_sql
--------------------------------------------------
NOTE
--------------------------------------------------
Advices generated with the assistance of an LLM. Independent verification of these advices is required due to the potential for inaccuracies.
--------------------------------------------------
ORIGINAL QUERY PLAN
--------------------------------------------------
Seq Scan on store_sales (cost=0.00..111292742.52 rows=1440384 width=115) (actual time=0.092..103093.207 rows=1306312.00 loops=1)
Filter: (NOT (ANY (ss_customer_sk = (SubPlan 1).col1)))
Rows Removed by Filter: 1574198
Buffers: shared hit=72987539
SubPlan 1
-> Index Scan using idx_sr_item_sk on store_returns (cost=0.42..76.74 rows=18 width=4) (actual time=0.005..0.034 rows=19.38 loops=2880510)
Index Cond: (sr_item_sk = store_sales.ss_item_sk)
Index Searches: 2880510
Buffers: shared hit=72933670
Planning Time: 0.257 ms
--------------------------------------------------
QUERY SUMMARY
--------------------------------------------------
The original query plan shows a Sequential Scan on store_sales with a correlated SubPlan for the NOT IN condition. For each of the 1.44 million rows in store_sales, it executes an Index Scan on store_returns, resulting in over 2.88 million index searches. This nested loop execution is the primary bottleneck, taking over 103 seconds. Converting the correlated NOT IN subquery to an anti-join (NOT EXISTS) will allow the optimizer to use a Hash Anti Join, processing both tables in bulk and significantly reducing execution time.
--------------------------------------------------
AI SUGGESTED QUERY 1
--------------------------------------------------
SELECT * FROM store_sales WHERE NOT EXISTS (SELECT 1 FROM store_returns WHERE store_returns.sr_item_sk = store_sales.ss_item_sk AND (store_returns.sr_customer_sk = store_sales.ss_customer_sk OR store_returns.sr_customer_sk IS NULL OR store_sales.ss_customer_sk IS NULL));
Reason: The original query uses a NOT IN subquery which is executed as a correlated subquery (SubPlan), leading to millions of index scans. Rewriting to NOT EXISTS allows the optimizer to use a Hash Anti Join, which is much more efficient for large datasets. The OR IS NULL conditions ensure strict semantic equivalence with NOT IN when dealing with NULL values.
--------------------------------------------------
REWRITTEN QUERY PLAN
--------------------------------------------------
Gather (cost=8541.96..139088.40 rows=154194 width=115)
Workers Planned: 2
-> Parallel Hash Anti Join (cost=7541.96..122669.00 rows=64248 width=115)
Hash Cond: (store_sales.ss_item_sk = store_returns.sr_item_sk)
Join Filter: ((store_returns.sr_customer_sk = store_sales.ss_customer_sk) OR (store_returns.sr_customer_sk IS NULL) OR (store_sales.ss_customer_sk IS NULL))
-> Parallel Seq Scan on store_sales (cost=0.00..65872.20 rows=1200320 width=115)
-> Parallel Hash (cost=6044.76..6044.76 rows=119776 width=8)
-> Parallel Seq Scan on store_returns (cost=0.00..6044.76 rows=119776 width=8)
--------------------------------------------------
AI SUGGESTED INDEX 1
--------------------------------------------------
CREATE INDEX idx_sr_item_customer ON store_returns (sr_item_sk, sr_customer_sk);
Reason: A composite index on (sr_item_sk, sr_customer_sk) allows index-only scans for the subquery or early aggregation, reducing table access and speeding up the anti-join condition evaluation.
Note: Indexes are suggested solely based on the given query, but they don't consider the overall system workload.
The suggested indexes improve the performance of the original query.
--------------------------------------------------
GUC FLAGS TUNING
--------------------------------------------------
SET work_mem = '64MB'; The current work_mem of 4MB is too small for a Hash Anti Join on tables with hundreds of thousands of rows. Increasing it to 64MB allows the hash table for store_returns to fit entirely in memory, preventing costly disk spills during the join.
Execution Time: 103167.475 ms
(50 rows)