Nouveaux types de données
Concerne : lors de la migration à partir des versions 2.5 et 3.0 de Firebird.
Comme indiqué précédemment, certaines expressions peuvent renvoyer de nouveaux types de données qui ne peuvent pas être interprétés par votre application sans la modifier.Un tel affinage peut prendre beaucoup de temps ou peut être au-delà de vos capacités.Pour simplifier la migration vers de nouvelles versions, vous pouvez définir le paramètre DataTypeCompatibility pour qu’il soit compatible avec la version souhaitée dans firebird.conf
ou databases.conf
.
DataTypeCompatibility = 3.0
ou
DataTypeCompatibility = 2.5
C’est le moyen le plus rapide d’assurer la compatibilité avec les nouveaux types de données.Cependant, au fil du temps, vous pouvez commencer à intégrer la prise en charge de nouveaux types dans votre application.Naturellement, cela se fera progressivement - d’abord un type, puis un autre et ainsi de suite.Dans ce cas, vous devez configurer le mappage des types dont vous n’avez pas encore finalisé la prise en charge avec d’autres types de données.L’opérateur SET BIND OF
est utilisé à cette fin.
SET BIND OF { <type-from> | TIME ZONE } TO { <type-to> | LEGACY | NATIVE | EXTENDED }
Le mot-clé LEGACY
dans la partie TO
est utilisé lorsqu’un type de données non présent dans une version précédente de Firebird doit être représenté d’une manière compréhensible pour les anciens logiciels clients (une certaine perte de données peut se produire). Il existe les conversions suivantes vers les types LEGACY
:
DataTypeCompatibility | Native type | Legacy type |
---|---|---|
2.5 |
BOOLEAN |
CHAR(5) |
2.5 ou 3.0 |
DECFLOAT |
DOUBLE PRECISION |
2.5 ou 3.0 |
INT128 |
BIGINT |
2.5 ou 3.0 |
TIME WITH TIME ZONE |
TIME WITHOUT TIME ZONE |
2.5 ou 3.0 |
TIMESTAMP WITH TIME ZONE |
TIMESTAMP WITHOUT TIME ZONE |
Lorsque le paramètre DataTypeCompatibility
est défini, les nouveaux types de données sont convertis en types hérités selon le tableau décrit ci-dessus.
Une description détaillée de cette déclaration est disponible dans "Firebird 4.0 Release Notes" et "Firebird 5.0 SQL Language Guide".Grâce à lui, vous pouvez contrôler l’affichage des nouveaux types dans votre application en exécutant la requête appropriée immédiatement après la connexion, et même écrire un déclencheur AFTER CONNECT
dans lequel vous pouvez utiliser plusieurs de ces opérateurs.
Par exemple, supposons que vous ayez ajouté le support de la date et de l’heure avec les fuseaux horaires à votre application, mais que vous n’ayez toujours pas le support des types INT128
et DECFLOAT
. Dans ce cas, vous pouvez écrire le trigger suivant.
create or alter trigger tr_ac_set_bind
on connect
as
begin
set bind of int128 to legacy;
set bind of decfloat to legacy;
end
Lecture agréée dans les transactions READ COMMITTED
Concerne : lors de la migration à partir des versions 2.5 et 3.0 de Firebird.
Firebird 4 introduit non seulement la cohérence en lecture (READ CONSISTENCY
) pour les requêtes dans les transactions READ COMMITTED
, mais en fait aussi le mode par défaut pour toutes les transactions READ COMMITTED
, indépendamment de leurs propriétés RECORD VERSION
ou NO RECORD VERSION
.
L’objectif est d’offrir aux utilisateurs un meilleur comportement, à la fois conforme à la spécification SQL et moins sujet aux conflits. Toutefois, ce nouveau comportement peut également avoir des effets secondaires inattendus.
Le plus important d’entre eux est sans doute le redémarrage lors de la gestion des conflits de mise à jour. Certains codes qui ne sont pas soumis au contrôle transactionnel peuvent ainsi être exécutés plusieurs fois dans PSQL. Voici quelques exemples de ce type de code :
-
l’utilisation de tableaux, de séquences ou de variables contextuelles externes ;
-
l’envoi de courriers électroniques à l’aide d’UDF ;
-
Utilisation de transactions hors ligne ou de requêtes externes.
Note
|
Dans le mode d’isolation |
Vous pouvez en savoir plus sur les lectures cohérentes dans les transactions READ COMMITTED
dans les "Firebird 4.0 Release Notes".
Un autre effet important est que les curseurs sous-déclarés dans les transactions READ COMMITTED READ CONSISTENCY
en mode lecture seule tiennent maintenant la collecte des déchets.Nous vous recommandons d’éviter d’utiliser une seule longue transaction READ COMMITTED READ ONLY
dans votre application, et de la remplacer par plusieurs transactions de ce type, chacune d’entre elles étant active exactement pendant la durée nécessaire.
Si les caractéristiques du mode READ CONSISTENCY
ne sont pas souhaitables pour une raison quelconque, le paramètre de configuration ReadConsistency
doit être mis à 0 pour revenir à l’ancien comportement.
Changements dans l’optimiseur
L’optimiseur change dans chaque version de Firebird. La plupart de ces changements sont positifs, c’est-à-dire que vos requêtes devraient s’exécuter plus rapidement, mais certaines requêtes peuvent ralentir. Vous devez donc tester les performances de votre application, et s’il y a un ralentissement quelque part, l’intervention du programmeur est nécessaire.
Pour la plupart des modifications de l’optimiseur, vous ne pouvez pas affecter le plan de requête en modifiant la configuration du serveur. Dans ce cas, vous pouvez procéder comme suit :
-
réécrire la requête SQL pour qu’elle s’exécute plus rapidement sur la nouvelle version du serveur ;
-
créer ou supprimer des index ;
-
Si aucune des solutions ci-dessus ne vous a aidé, créez un ticket de régression à l’adresse suivante FirebirdSQL ticket.
Il y a quelques éléments de l’optimiseur qui peuvent être affectés par la modification de la configuration :
Utilisation de Refetch pour le tri de grands ensembles de données
Concerne : lors de la migration à partir des versions 2.5 et 3.0 de Firebird.
Depuis Firebird 4.0, une nouvelle méthode d’accès Refetch
a été introduite pour optimiser le tri des ensembles de données larges. Un ensemble de données large est un ensemble de données dans lequel la longueur totale des champs d’enregistrement est importante.
Historiquement, lorsqu’il effectue un tri externe, Firebird écrit à la fois les champs clés (c’est-à-dire ceux spécifiés dans la phrase ORDER BY
ou GROUP BY
) et les champs non-clés (tous les autres champs référencés dans la requête) dans des blocs de tri qui sont soit stockés en mémoire, soit dans des fichiers temporaires. Une fois le tri terminé, ces champs sont relus à partir des blocs de tri.Cette approche est généralement considérée comme plus rapide car les enregistrements sont lus à partir des fichiers temporaires dans l’ordre des enregistrements triés, plutôt que d’être sélectionnés de manière aléatoire à partir de la page de données.Cependant, si les champs non-clés sont grands (par exemple, de longs VARCHARs sont utilisés), cela augmente la taille des blocs de tri et résulte donc en plus d’opérations d’entrées-sorties pour les fichiers temporaires. Firebird 4 offre une approche alternative (méthode d’accès Refetch
) où seuls les champs clés et les enregistrements DBKEY
sont stockés à l’intérieur des blocs de tri, et les champs non-clés sont récupérés à partir des pages de données après le tri. Cela permet d’améliorer les performances de tri dans le cas de longs champs non clés.
Ainsi, les plans de vos requêtes qui utilisent le tri peuvent changer. Un nouveau paramètre de configuration InlineSortThreshold
est introduit pour contrôler cette méthode d’accès. La valeur spécifiée pour InlineSortThreshold
définit la taille maximale d’un enregistrement de tri (en octets) qui peut être stocké en ligne, c’est-à-dire à l’intérieur d’un bloc de tri. Zéro signifie que les enregistrements sont toujours rechargés. La valeur optimale de ce paramètre doit être choisie de manière expérimentale. La valeur par défaut est de 1000 octets.
Prenons l’exemple suivant :
SELECT
field_1, field_2, field_3, field_4
FROM SomeTable
ORDER BY field_1
Avant Firebird 4.0, les 4 champs étaient toujours inclus dans les blocs de tri. Depuis Firebird 4.0, si la longueur totale des champs field_1 . field_4
dépasse la valeur de InlineSortThreshold
, seul field_1
sera inclus dans les blocs de tri et ensuite Refetch
sera exécuté.
Conversion des JOIN OUTER en JOIN INNER
L’optimisation des JOIN OUTER dans Firebird pose un certain nombre de problèmes.
Tout d’abord, le OUTER JOIN ne peut actuellement être exécuté que par un seul algorithme de connexion NESTED LOOP JOIN, ce qui pourrait être modifié dans les versions futures.
Deuxièmement, lorsque les threads sont reliés par des connexions externes, l’ordre de connexion est strictement fixe, c’est-à-dire que l’optimiseur ne peut pas le modifier pour que le résultat reste correct.
Cependant, s’il y a un prédicat pour le champ WHERE
de la table "de droite" (jointe) dans la condition WHERE
qui ne gère pas explicitement la valeur NULL
, il n’y a pas d’intérêt à faire une jointure externe. Dans ce cas, à partir de Firebird 5.0, une telle jointure sera convertie en jointure interne, permettant à l’optimiseur d’appliquer la gamme complète des algorithmes de jointure disponibles.
Supposons que vous ayez la requête suivante :
SELECT
COUNT(*)
FROM
HORSE
LEFT JOIN FARM ON FARM.CODE_FARM = HORSE.CODE_FARM
WHERE FARM.CODE_COUNTRY = 1
Firebird 5.0 convertira implicitement une telle requête en une forme équivalente :
SELECT
COUNT(*)
FROM
HORSE
JOIN FARM ON FARM.CODE_FARM = HORSE.CODE_FARM
WHERE FARM.CODE_COUNTRY = 1
Si LEFT JOIN
a été utilisé comme un indice pour spécifier l’ordre de jointure de manière très active, il peut être problématique de réécrire de nombreuses requêtes d’une nouvelle manière. Pour ces développeurs, il existe un paramètre de configuration OuterJoinConversion
dans firebird.conf
ou database.conf
. Mettre le paramètre OuterJoinConversion
à false
désactive la transformation des jointures externes en jointures internes. Notez que ce paramètre est une solution temporaire pour faciliter la migration et peut être supprimé dans les versions futures de Firebird.
RETURNING, retour d’un ensemble d’enregistrements
Depuis Firebird 5.0, les instructions de modification du client INSERT . SELECT
, UPDATE
, DELETE
, UPDATE OR INSERT
et MERGE
contenant une clause RETURNING
retournent un curseur, c’est à dire qu’elles sont capables de retourner plusieurs enregistrements au lieu de donner l’erreur "multiple rows in singleton select" comme auparavant.
Ces requêtes pendant la préparation sont maintenant décrites comme isc_info_sql_sql_stmt_select
, alors que dans les versions précédentes elles étaient décrites comme isc_info_sql_sql_stmt_exec_procedure
.
Les opérateurs singleton INSERT … VALUES
, ainsi que les instructions UPDATE
et DELETE
positionnées (c’est-à-dire, qui contiennent une clause WHERE CURRENT OF
) conservent le comportement existant et sont décrites comme isc_info_sql_sql_stmt_exec_procedure
.
Cependant, toutes ces requêtes, si elles sont utilisées dans PSQL et que la phrase RETURNING
est appliquée, sont toujours traitées comme des singletons.
Si votre application utilise des instructions de modification INSERT . SELECT
, UPDATE
, DELETE
, UPDATE OR INSERT
, et MERGE
contenant une phrase RETURNING
, elle peut provoquer des erreurs. Assurez-vous que votre pilote ou composant d’accès gère correctement ces requêtes, et si ce n’est pas le cas, modifiez le code (de l’application ou du composant) ou attendez une mise à jour du pilote/composant correspondant qui gère ces requêtes correctement.
Exemples de modification d’opérateurs contenant RETURNING, et de retour d’un ensemble de données :
INSERT INTO dest(name, val)
SELECT desc, num + 1 FROM src WHERE id_parent = 5
RETURNING id, name, val;
UPDATE dest
SET a = a + 1
WHERE id = ?
RETURNING id, a;
DELETE FROM dest
WHERE price < 0.52
RETURNING id;
MERGE INTO PRODUCT_INVENTORY AS TARGET
USING (
SELECT
SL.ID_PRODUCT,
SUM(SL.QUANTITY)
FROM
SALES_ORDER_LINE SL
JOIN SALES_ORDER S ON S.ID = SL.ID_SALES_ORDER
WHERE S.BYDATE = CURRENT_DATE
AND SL.ID_PRODUCT = :ID_PRODUCT
GROUP BY 1
) AS SRC(ID_PRODUCT, QUANTITY)
ON TARGET.ID_PRODUCT = SRC.ID_PRODUCT
WHEN MATCHED AND TARGET.QUANTITY - SRC.QUANTITY <= 0 THEN
DELETE
WHEN MATCHED THEN
UPDATE SET
TARGET.QUANTITY = TARGET.QUANTITY - SRC.QUANTITY,
TARGET.BYDATE = CURRENT_DATE
RETURNING OLD.QUANTITY, NEW.QUANTITY, SRC.QUANTITY;
Conclusion
Dans cet article, j’ai essayé de décrire les problèmes les plus courants et leurs solutions lors de la migration vers Firebird 5.0 à partir de Firebird 2.5, 3.0 et 4.0. J’espère que cet article vous aidera à migrer vos bases de données et vos applications vers Firebird 5.0 et à profiter de tous les avantages de la nouvelle version.