PostgreSQL
 sql >> Database >  >> RDS >> PostgreSQL

Quando sono pianificate le query (SELECT)?

Non posso parlare dell'interfaccia Perl lato client in sé, ma posso fare un po' di luce sul lato server PostgreSQL.

PostgreSQL ha preparato istruzioni e istruzioni non preparate. Le istruzioni non preparate vengono analizzate, pianificate ed eseguite immediatamente. Inoltre non supportare la sostituzione dei parametri. Su un semplice psql shell puoi mostrare il loro piano di query in questo modo:

tmpdb> explain select * from sometable where flag = true;

D'altra parte ci sono istruzioni preparate:di solito (vedi "eccezione" di seguito) analizzate e pianificate in un passaggio ed eseguite in un secondo passaggio. Possono essere rieseguiti più volte con parametri diversi, perché lo fanno supportare la sostituzione dei parametri. L'equivalente in psql è questo:

tmpdb> prepare foo as select * from sometable where flag = $1;
tmpdb> explain execute foo(true);

Potresti vedere che il piano è diverso dal piano nella dichiarazione impreparata, perché la pianificazione è avvenuta già nella prepare fase come descritto nel documento per PREPARARE :

Ciò significa anche che il piano NON ottimizzato per i parametri sostituiti:nei primi esempi potrebbe essere utilizzato un indice per flag perché PostgreSQL sa che all'interno di un milione di voci solo dieci hanno il valore true . Questo ragionamento è impossibile quando PostgreSQL utilizza un'istruzione preparata. In tal caso viene creato un piano che funzionerà per tutti i possibili valori dei parametri nel miglior modo possibile. Questo potrebbe escludere l'indice menzionato perché il recupero della parte migliore della tabella completa tramite accesso casuale (a causa dell'indice) è più lento di una semplice scansione sequenziale. Il PREPARARE doc lo conferma:

A proposito - Per quanto riguarda la memorizzazione nella cache del piano, PREPARARE doc ha anche qualcosa da dire:

Inoltre, non è prevista la memorizzazione nella cache del piano né la memorizzazione nella cache/riutilizzo su più connessioni.

ECCEZIONE :Ho menzionato "solitamente". Il psql mostrato gli esempi non sono le cose che un adattatore client come Perl DBI usa davvero. Utilizza un certo protocollo . Qui il termine "query semplice" corrisponde alla "query non preparata" in psql , il termine "query estesa " corrisponde a "query preparata" con un'eccezione:esiste una distinzione tra (una) "istruzione senza nome" e (possibilmente più) "dichiarazioni con nome". Per quanto riguarda le dichiarazioni con nome, doc dice:

e anche:

Quindi in questo caso la pianificazione viene eseguita senza parametri come descritto sopra per PREPARE - niente di nuovo.

L'eccezione menzionata è la "dichiarazione senza nome". Il documento dice:

Ed ecco il vantaggio:sebbene l'istruzione senza nome sia "preparata" (cioè può avere la sostituzione di parametri), può anche adattare il piano di query ai parametri effettivi.

A proposito:l'esatta gestione dell'istruzione senza nome è cambiata più volte nelle versioni precedenti del server PostgreSQL. Puoi cercare i vecchi documenti per i dettagli, se lo desideri.

Motivazione - Perl/qualsiasi client :

Come un cliente come Perl usa il protocollo è una domanda completamente diversa. Alcuni client come il driver JDBC per Java fondamentalmente dicono:anche se il programmatore utilizza un'istruzione preparata, le prime cinque (o giù di lì) esecuzioni sono mappate internamente su una "interrogazione semplice" (cioè effettivamente impreparata), dopodiché il driver passa a " dichiarazione nominativa".

Quindi un cliente ha queste scelte:

  • Forza ogni volta la (ri)pianificazione utilizzando il protocollo "query semplice".
  • Pianifica una volta, esegui più volte utilizzando il protocollo "query estesa" e l'"istruzione denominata" (il piano potrebbe non essere valido perché la pianificazione viene eseguita senza parametri).
  • Analizza una volta, pianifica ogni esecuzione (con la versione corrente di PostgreSQL) usando il protocollo "query estesa" e la "istruzione senza nome" e obbedendo ad alcune altre cose (fornire alcuni parametri durante il messaggio "analisi")
  • Gioca a trucchi completamente diversi come il driver JDBC.

Cosa fa attualmente Perl:non lo so. Ma la citata "derivazione" non è molto improbabile.