Par défaut, une fonction est juste une « boîte noire » dont la base de données connait très peu le comportement. De ce fait, il peut arriver que les requêtes utilisant la fonction se trouvent exécutées beaucoup moins efficacement qu'elles ne pourraient. Il est possible de fournir une connaissance supplémentaire qui aide le planificateur à optimiser les appels de fonctions.
     Quelques indications basiques peuvent être données via les annotations
     déclaratives présentes dans la commande CREATE FUNCTION.
     La plus importante de celles-ci est la 
      catégorie de volatilité (IMMUTABLE, STABLE,
     ou VOLATILE) ; on doit toujours être très soucieux
     de la spécifier correctement lorsqu'on définit une fonction.
     La propriété de sûreté face au parallélisme (PARALLEL
      UNSAFE, PARALLEL RESTRICTED, ou
     PARALLEL SAFE) doit également être spécifiée
     pour espérer utiliser la fonction dans des requêtes parallélisées.
     Il peut aussi être utile de spécifier le coût estimé de l'exécution
     de la fonction, et le nombre de lignes qu'une fonction
     renvoyant un ensemble d'enregistrements est estimée renvoyer.
     Toutefois, la manière déclarative de spécifier ces deux informations
     ne permet seulement que de donner une valeur constante, ce qui est
     souvent inadéquat.
    
Il est aussi possible de rattacher une fonction de support de planification à une fonction appelable en SQL (appelée fonction cible), et ainsi de fournir sur la fonction cible une connaissance qui serait trop complexe à être représentée déclarativement. Les fonctions de support de planification doivent être écrites en C (alors que leurs fonctions cibles peuvent ne pas l'être), ce qui en fait une fonctionnalité avancée que relativement peu de personnes utiliseront.
Une fonction de support de planification doit avoir la signature SQL
supportfn(internal) returns internal
     
     Elle est rattachée à sa fonction cible en spécifiant la clause
     SUPPORT dans la création de la fonction cible.
    
     Les détails de l'API des fonctions de support de planification
     se trouvent dans le fichier
     src/include/nodes/supportnodes.h dans le code
     source de PostgreSQL. Ici, on ne fournit
     qu'une vue d'ensemble de ce que les fonctions de support de planification
     peuvent faire.
     L'ensemble des demandes possibles adressables à une fonction de support
     est extensible, si bien que d'autres choses seront possibles dans
     des versions ultérieures.
    
     Certains appels de fonctions peuvent être simplifiés lors de la
     planification en se basant sur les propriétés spécifiques de la fonction.
     Par exemple, int4mul(n, 1) pourrait être simplifié par
     n. Ce type de transformation peut être exécuté
     par une fonction de support de planification, en lui faisant implémenter
     le type de demande SupportRequestSimplify.
     La fonction de support va être appelée pour chaque instance de la
     fonction cible trouvée dans l'arbre d'analyse de la requête.
     Si elle trouve qu'un appel particulier peut être simplifié en
     une autre forme, elle est capable de construire et renvoyer
     un arbre d'analyse représentant cette expression. Cela fonctionnera
     automatiquement pour les opérateurs basés sur cette fonction,
     également  --  dans l'exemple juste ci-dessus, n * 1
     serait aussi simplifié en n.
     (Mais notez que c'est juste un exemple ; cette optimisation particulière
     n'est pas réellement mise en œuvre par PostgreSQL.)
     Nous ne garantissons pas que PostgreSQL n'appelera
     jamais la fonction cible dans les cas que la fonction de support pourrait
     simplifier. Assurez-vous d'une équivalence rigoureuse entre l'expression
     simplifiée et l'exécution réelle de la fonction cible.
    
     Pour les fonctions cible qui renvoient un booléen, il est souvent utile
     d'estimer la fraction des lignes qui vont être sélectionnées par une clause
     WHERE utilisant cette fonction. Ceci est réalisable avec
     une fonction de support qui implémente le type de demande
     SupportRequestSelectivity.
    
     Si le temps d'exécution d'une fonction cible est très dépendant
     de ses entrées, il peut être utile de fournir un coût d'exécution
     non constant pour celle-ci.
     Ceci est réalisable avec une fonction de support implémentant
     le type de demande SupportRequestCost.
    
     Pour les fonctions cibles qui renvoient des ensembles de lignes,
     il est souvent utile de fournir une estimation non constante du
     nombre de lignes renvoyées.
     Ceci est réalisable avec une fonction de support implémentant
     le type de demande SupportRequestRows.
    
     Pour les fonctions cibles qui renvoient un booléen, il est envisageable
     de convertir un appel de fonction au niveau d'un WHERE vers une ou
     plusieurs clauses d'un opérateur indexable. Ces clauses peuvent être
     exactement équivalentes à la condition de la fonction, ou bien elles peuvent
     être plus faibles (c'est-à-dire qu'elles peuvent accepter certaines
     valeurs que la condition via la fonction n'accepte pas).
     Dans ce dernier cas, la condition d'index est dite
     avec perte; elle peut toujours être utilisée
     pour un parcours d'index, mais la fonction devra être appelée pour chaque
     ligne renvoyée par l'index pour vérifier qu'elle satisfait la condition
     WHERE.
     Pour créer de telles conditions, la fonction de support doit implémenter
     le type de demande SupportRequestIndexCondition.