0 Abonnés · 130 Publications

SQL est un langage standard pour stocker, manipuler et récupérer des données dans des bases de données relationnelles.

Article Sylvain Guilbaud · Nov 6, 2025 5m read

Introduction

Dans mon article précédent, j'ai présenté le module IRIStool, qui intègre de manière transparente la bibliothèque pandas pour Python à la base de données IRIS. Je vais maintenant vous expliquer comment utiliser IRIStool pour exploiter InterSystems IRIS comme base pour une recherche sémantique intelligente dans les données de soins de santé au format FHIR.

Cet article décrit ce que j'ai fait pour créer une base de données pour mon autre projet, FHIR Data Explorer. Les deux projets sont candidats au concours InterSystems actuel, alors n'hésitez pas à voter pour eux si vous les trouvez utiles.

Ils sont disponibles sur Open Exchange:

Dans cet article, nous aborderons les sujets suivants:

  • Connexion à la base de données InterSystems IRIS via Python
  • Création d'un schéma de base de données compatible FHIR
  • Importation de données FHIR au moyen d'intégrations vectorielles pour la recherche sémantique

Conditions préalables

Installez IRIStool à partir de la page Github IRIStool et Data Manager.

1. Configuration de la connexion IRIS

Commencez par configurer votre connexion à l'aide des variables d'environnement dans un fichier .env:

IRIS_HOST=localhost
IRIS_PORT=9092
IRIS_NAMESPACE=USER
IRIS_USER=_SYSTEM
IRIS_PASSWORD=SYS

Connectez-vous à IRIS à l'aide du gestionnaire de contexte du module IRIStool:

from utils.iristool import IRIStool
import os
from dotenv import load_dotenv

load_dotenv()

with IRIStool( host=os.getenv('IRIS_HOST'), port=os.getenv('IRIS_PORT'), namespace=os.getenv('IRIS_NAMESPACE'), username=os.getenv('IRIS_USER'), password=os.getenv('IRIS_PASSWORD') ) as iris: # IRIStool manages the connection automatically pass

2. Création du schéma FHIR

Commencez par créer une table pour stocker les données FHIR, puis, tout en extrayant les données des paquets FHIR, créez des tables avec des capacités de recherche vectorielle pour chacune des ressources FHIR extraites (comme Patient, Osservability, etc.). 

Le module IRIStool simplifie la création de tables et d'index!

Table de référentiel FHIR

# Créer une table de référentiel principal pour les paquets FHIR brutsifnot iris.table_exists("FHIRrepository", "SQLUser"):
    iris.create_table(
        table_name="FHIRrepository",
        columns={
            "patient_id": "VARCHAR(200)",
            "fhir_bundle": "CLOB"
        }
    )
    iris.quick_create_index(
        table_name="FHIRrepository",
        column_name="patient_id"
    )

Table de patients avec support vectoriel

# Création d'une table de patients au moyen de la colonne vectorielle pour la recherche sémantiqueifnot iris.table_exists("Patient", "SQLUser"):
    iris.create_table(
        table_name="Patient",
        columns={
            "patient_row_id": "INT AUTO_INCREMENT PRIMARY KEY",
            "patient_id": "VARCHAR(200)",
            "description": "CLOB",
            "description_vector": "VECTOR(FLOAT, 384)",
            "full_name": "VARCHAR(200)",
            "gender": "VARCHAR(30)",
            "age": "INTEGER",
            "birthdate": "TIMESTAMP"
        }
    )
<span class="hljs-comment"># Création d'index standards</span>
iris.quick_create_index(table_name=<span class="hljs-string">"Patient"</span>, column_name=<span class="hljs-string">"patient_id"</span>)
iris.quick_create_index(table_name=<span class="hljs-string">"Patient"</span>, column_name=<span class="hljs-string">"age"</span>)

<span class="hljs-comment"># Création d'un index vectoriel HNSW pour la recherche par similarité</span>
iris.create_hnsw_index(
    index_name=<span class="hljs-string">"patient_vector_idx"</span>,
    table_name=<span class="hljs-string">"Patient"</span>,
    column_name=<span class="hljs-string">"description_vector"</span>,
    distance=<span class="hljs-string">"Cosine"</span>
)</code></pre>

3. Importation de données FHIR à l'aide de vecteurs

Générez facilement des intégrations vectorielles à partir des descriptions des patients FHIR et insérez-les dans IRIS:

from sentence_transformers import SentenceTransformer

# Initialisation du modèle de convertisseur model = SentenceTransformer('sentence-transformers/all-MiniLM-L6-v2')

# Exemple : Traitement des données du patient patient_description = "45-year-old male with hypertension and type 2 diabetes" patient_id = "patient-123"# Création d'un encodage vectoriel vector = model.encode(patient_description, normalize_embeddings=True).tolist()

# Insertion des données du patient à l'aide du vecteur iris.insert( table_name="Patient", patient_id=patient_id, description=patient_description, description_vector=str(vector), full_name="John Doe", gender="male", age=45, birthdate="1979-03-15" )

4. Recherche sémantique

Lorsque vos données sont téléchargées, vous pouvez effectuer des recherches par similarité:

# Requête de recherche
search_text = "patients with diabetes"
query_vector = model.encode(search_text, normalize_embeddings=True).tolist()

# définition de requête SQL query = f""" SELECT TOP 5 patient_id, full_name, description, VECTOR_COSINE(description_vector, TO_VECTOR(?)) as similarity FROM Patient ORDER BY similarity DESC """# définition des paramètres de requête parameters = [str(query_vector)]

# Recherche de patients similaires à l'aide de la recherche vectorielle results = iris.query(query, parameters)

# Impression des données du DataFrameifnot results.empty: print(f"{results['full_name']}: {results['similarity']:.3f}")

Conclusion

  • Le module IRIStool simplifie l'intégration d'IRIS avec des méthodes Python intuitives pour la création de tables et d'index
  • IRIS prend en charge le stockage hybride SQL + vecteur de manière native, ce qui permet de réaliser les deux requêtes traditionnelles et la recherche sémantique
  • Les intégrations vectorielles permettent une recherche intelligente dans les données de soins de santé FHIR à l'aide du langage naturel
  • Les index HNSW fournissent une recherche par similarité efficace à grande échelle

Cette approche prouve qu'InterSystems IRIS peut servir de base solide pour créer des applications de santé intelligentes avec des capacités de recherche sémantique sur les données FHIR.

0
0 8
InterSystems officiel Adeline Icard · Oct 24, 2025

Les versions de maintenance 2025.1.2 et 2024.1.5 de la plateforme de données InterSystems IRIS, d'InterSystems IRIS for Health et d'HealthShare Health Connect sont désormais disponibles en disponibilité générale (GA). Ces versions incluent les correctifs pour plusieurs alertes et avis publiés récemment, notamment :

0
0 15
Article Corentin Blondeau · Oct 13, 2025 4m read

Bonjour

Je vous soumets cet article en tant qu’état de l’art enrichi.
L’objectif est de réunir les différentes façons d’importer et d’exporter des CSV en un seul endroit.
Cet article est basé sur InterSystems 2024.1 .
N'hésitez pas à commenter pour rajouter des précisions.
Si vous voulez une deuxième partie sur l'export de CSV, faites le moi savoir.

Contexte

3
2 63
Article Guillaume Rongier · Oct 15, 2025 9m read

Vous êtes familier avec les bases de données SQL, mais vous ne connaissez pas IRIS ? Alors lisez la suite...

Il y a environ un an, j'ai rejoint InterSystems, et c'est ainsi que j'ai découvert IRIS.  J'utilise des bases de données depuis plus de 40 ans, la plupart du temps pour des fournisseurs de bases de données, et je pensais qu'IRIS serait similaire aux autres bases de données connues.  Cependant, j'ai été surpris de constater qu'IRIS est très différente par rapport aux autres bases de données, et souvent bien meilleure.  Avec mon premier article dans la communauté Dev, je vais présenter IRIS de manière générale aux personnes qui connaissent déjà d'autres bases de données telles qu'Oracle, SQL Server, Snowflake, PostgeSQL, etc.   J'espère vous rendre les choses plus claires et plus simples et vous faire gagner du temps pour vous lancer.

Tout d'abord, IRIS prend en charge les commandes et la syntaxe SQL de la norme ANSI. Il dispose de tables, de colonnes, de types de données, de procédures stockées, de fonctions...   bref, tout ce qui concerne les relations.  Et vous pouvez utiliser ODBC, JDBC, DBeaver ou tout autre navigateur de base de données que vous préférez.  Donc, oui, la plupart des connaissances et des opérations que vous maîtrisez avec d'autres bases de données fonctionneront très bien avec IRIS.  Youpi!  

Mais qu'en est-il de ces différences que j'ai mentionnées?  Bien, attachez vos ceintures:

Multi-Model: IRIS est une base de données relationnelle, mais c'est aussi une base de données orientée objet, un magasin de documents, et elle prend en charge les vecteurs, les cubes/MDX, et... vous comprenez où je veux en venir.  Ce qui est incroyable, c'est que vous pouvez profiter de tous ces modèles... dans la même instruction SQL!  Et bien souvent, les données peuvent être stockées sous plusieurs de ces structures de données — sans avoir à les sauvegarder à deux reprises — ni à utiliser plusieurs types de bases de données!  Lorsque vous accédez à des données identiques comme s'il s'agissait de modèles différents, InterSystems parle de CDP (Common Data Plane, ou plan de données commun).  C'est pour le moins rare, voire unique, dans le secteur des bases de données.  Personne ne s'intéressait vraiment au CDP jusqu'à ce que la révolution de l'IA rende tout à coup indispensable la prise en charge du multimodèle. Il ne s'agit pas d'une fonctionnalité que d'autres bases de données sont susceptibles d'implémenter, car elle est intégrée au cœur même du noyau.  IRIS facilite l'utilisation des modèles multiples ainsi que des technologies NoSQL et NewSQL pour les utilisateurs SQL:

Pour la base de données Object, vous extrayez une clé-valeur de l'arborescence JSON, qui correspond simplement à la valeur d'une table classique. 

-- exemple de requête dans une base de données ObjectSELECT JSON_OBJECT('product':Product,'sizes':PopularSizes) FROM Sample.Clothing

-- Cela renvoie une liste de paires clé-valeur. Si une paire manque, -- IRIS crée par défaut une paire avec une valeur nulle.

En ce qui concerne Vector, considérez-le simplement comme un autre type de données, mais avec certaines fonctions spéciales qui ne fonctionnent qu'avec le type de données en question 

-- exemple de création d'une table avec une colonne vectorielleCREATETABLE Sample.CustEventV1 (
  CustID INTEGER,
  EventDt DATE,
  Vtest VECTOR(integer,4),
  EventValue NUMERIC(12,2),  
  EventCD VARCHAR(8)) 

-- Vous pouvez utiliser des fonctions telles que VECTOR_DOT_PRODUCT ou VECTOR_COSINE sur Vtest

Taxonomie:  les différents fournisseurs de bases de données n'utilisent pas tels termes comme base de données, schéma, déploiement, instance, etc. exactement de la même manière. 

  • Instance: lorsque vous installez le logiciel de base de données, généralement appelé 'instance' par les éditeurs de bases de données. J'entends parfois ce terme chez InterSystems, mais plus souvent, j'entends le terme 'déploiement'.  Cela s'explique probablement par le fait que le terme 'instance' est déjà utilisé dans le monde orienté objet.  Quel que soit le terme utilisé, la hiérarchie pour les autres bases de données est généralement la suivante:
    • instance/déploiement
      • base de deonnées
        • schéma
          • tables, vues, etc.

            .. ou bien:

  • instance/déploiement (il *s'agit* de la base de données)
    • schéma
      • tables, vues, etc.

            .. mais IRIS est un peu différent dans la mesure où il comporte une couche supplémentaire appelée 'espace de nom':

  • instance/déploiement
    • espace de nom
      • base de données
        • schéma
          • tables, viues, etc.

Un espace de noms est une entité logique qui contient des bases de données. Cependant, plusieurs espaces de noms peuvent contenir la même base de données, il ne s'agit donc peut-être pas d'une hiérarchie.  Il est principalement utilisé pour le contrôle d'accès. Et il peut contenir des bases de données provenant d'autres instances/déploiements!

HA: La haute disponibilité (High Availability) est obtenue grâce à une technique appelée mise en miroir ( mirroring ).  Il s'agit d'un type de réplication où l'intégralité de la base de données est répliquée, y compris le code.  Vous pensez peut-être que vous ne souhaitez pas répliquer l'intégralité de la base de données.  Mais grâce aux espaces de noms, vous pouvez considérer une base de données comme une sorte de schéma et diviser vos données de manière à ce que celles que vous souhaitez mettre en miroir et celles que vous ne souhaitez pas mettre en miroir se trouvent dans des bases de données distinctes. 

Stockage du code: Oui, vous avez parfaitement compris: lorsque vous mettez une base de données en miroir, le code est également transféré!  Il s'agit d'une fonctionnalité très récente pour certaines bases de données à la mode, mais IRIS l'offre depuis toujours. Vous pouvez stocker à la fois le code et les données dans la même base de données, mais le plus souvent, les utilisateurs préfèrent les séparer.

ECP: Bien; c'est le protocole Enterprise Cache Protocol qui rend IRIS vraiment intéressant.  Je ne savais même pas que cela était possible, mais j'ai récemment découvert qu'il existe quelques bases de données NoSQL peu connues qui le permettent.  Avec le protocole ECP vous pouvez configurer le système de manière à ce que différents déploiements puissent partager leurs caches!  Oui, je veux bien dire leurs caches memory réels.. et non pas le partage des données des tables. Pour ce faire, le cache d'un déploiement est automatiquement synchronisé avec celui d'un autre déploiement.  C'est ce qu'on appelle être synchronisé!  C'est très facile à configurer, même si cela doit être compliqué en coulisses. Il s'agit d'un tout autre type de mise à l'échelle horizontale qui peut rendre les applications ultra-rapides.

Translytique: Ce terme, translytique, est utilisé pour décrire une base de données qui est à la fois OLTP et OLAP. Il peut également être appelé HTAP ou HOAP. Parfois, on emploie le terme hybride mais ce terme est trop utilisé dans le monde technologique, je vais donc m'en tenir au terme commençant par T.  Au début, toutes les bases de données étaient translytiques.  Mais avec l'avènement des structures en colonnes et d'autres structures, ainsi que de nouveaux types de stockage (par exemple le stockage en blocs par opposition au stockage en blobs) elles ont été séparées en OLTP et OLAP. Aujourd'hui, les fournisseurs tentent de les réunir à nouveau.   Il est beaucoup plus facile d'ajouter OLAP à un noyau OLTP que de faire l'inverse. Bien sûr, les fournisseurs de solutions DW peuvent ajouter quelques indexations pour les recherches sur une seule ligne, mais je doute qu'ils ajoutent rapidement la prise en charge de fonctionnalités complexes telles que les déclencheurs et les insertions/mises à jour rapides. Le fait est que l'OLTP rapide est plus compliqué à construire que l'OLAP... c'est une technologie beaucoup plus mature. IRIS est une excellente base de données translytique (voir les évaluations des analystes pour comprendre pourquoi). Par exemple, certaines bases de données prennent en charge à la fois le stockage en lignes et en colonnes, mais dans des tables différentes.  IRIS peut disposer de colonnes de stockage en lignes dans la même table que les colonnes de stockage en colonnes.

/* Exemple de combinaison entre stockage en lignes et stockage en colonnes. 
   Toutes les colonnes sont stockées en lignes (par défaut), à l'exception de EventValue.
   EventValue est explicitement définie comme stockage en colonnes. 
   Si vous interrogiez la valeur moyenne de EventValue pour l'ensemble de la table, la réponse serait RAPIDE! */CREATETABLE Sample.CustEvent (
  CustID INTEGER,
  EventDt DATE,
  EventValue NUMERIC(12,2) WITH STORAGETYPE = COLUMNAR,
  EventCD VARCHAR(8))

Installation: Avec d'autres bases de données, vous devez généralement les installer quelque part (sur site ou dans le cloud), comme vous le faites avec Postgres ou SQL Server, ou bien recourir à un SAAS cloud tel que RedShift ou Snowflake. Avec IRIS, cela dépend. Il y a trois moyens d'obtenir IRIS : via une licence, via un service géré ou via Cloud SQL. 

  1. Grâce à une licence, vous pouvez l'installer, le configurer et le maintenir de manière indépendante. Cela peut se faire sur site ou sur le cloud de votre choix. J'ai surtout entendu parler de son utilisation sur AWS, Azure, GCP et TenCent.
  2. Grâce à un service géré, InterSystems installe, configure et assure la maintenance d'IRIS pour vous via un cloud public. 
  3. Grâce à Cloud SQL, il est possible de bénéficier d'un service SAAS (ou devrais-je dire PAAS ? DBAAS ?).  Vous n'avez rien à installer.  Il est conçu pour s'intégrer dans des systèmes plus vastes en tant que module composable, n'offrant qu'un sous-ensemble des fonctionnalités IRIS, telles que SQL et les fonctions d'apprentissage automatique (ML).  La suite de cet article concerne IRIS sous licence ou IRIS géré, et ne concerne pas Cloud SQL.

Langages intégrés: Outre SQL, IRIS a toujours pris en charge un langage orienté objet appelé ObjectScript, qui est un dérivé du langage médical MUMPS. Il s'agit d'un langage très puissant, mais peu connu. Ne vous inquiétez pas, IRIS prend également en charge Python intégré. 

Documentation: Comme IRIS a toujours été étroitement lié à ObjectScript, la documentation a tendance à utiliser une terminologie orientée objet.  Vous trouverez donc des termes simples tels que tables désignés par 'classes persistentes'.  Mais cela semble disparaître de la documentation au fil du temps, et vous pouvez tout simplement ignorer ces termes, sauf si vous souhaitez devenir programmeur IRIS.

IRIS prend donc en charge le langage SQL que vous connaissez et appréciez, ainsi que Python, il est translytique, fonctionne sur site ou dans le cloud, est multimodèle et dispose de fonctionnalités futuristes telles que l'ECP.  Il y a bien d'autres choses encore mais ce sont celles-ci qui m'ont paru les plus importantes et interessantes.  Je pense qu'elles pourraient être utiles à d'autres développeurs SQL et administrateurs de bases de données provenant d'autres produits.   Si c'est votre cas et que vous essayez IRIS, je souhaiterais connaître votre avis sur votre expérience.

0
0 27
Article Iryna Mykhailova · Oct 14, 2025 9m read

Dans mon article précédent, « Utilisation de LIKE avec des variables et des modèles dans SQL », nous avons exploré le comportement du prédicat LIKE dans différents scénarios, de l'Embedded SQL au Dynamic SQL, et l'impact sur les performances lorsque des caractères génériques et des variables entrent en jeu. Cet article visait à se familiariser avec l'écriture d'une requête LIKE fonctionnelle. Mais écrire du SQL efficace n'est que le point de départ. Pour créer des applications fiables, évolutives et sécurisées, vous devez comprendre les bonnes pratiques qui sous-tendent tout SQL, y compris les requêtes utilisant LIKE.

Cet article franchit une nouvelle étape. Nous aborderons quelques points clés pour renforcer votre code SQL, éviter les pièges courants et garantir l'exécution correcte, efficace et sécurisée de vos instructions SELECT. J'utiliserai les instructions SELECT avec le prédicat LIKE comme exemple, montrant comment ces principes généraux affectent directement vos requêtes et leurs résultats.

0
0 21
Article Lorenzo Scalese · Oct 6, 2025 5m read

Commençons par une question simple et motivante : au cours des 14 derniers jours, quelles sont les erreurs les plus courantes dans le Journal des erreurs d'application?

Répondre à cette question via le portail de gestion ou le terminal est un processus manuel fastidieux. Nous devrions pouvoir simplement utiliser SQL. Heureusement, quelques requêtes de classe sont disponibles  pour vous aider dans la classe SYS.ApplicationError de l'espace de noms %SYS. Vous pouvez répondre à cette question pour une seule date à l'aide d'une commande telle que:

select"Error message",count(*)
from SYS.ApplicationError_ErrorList('CCR','12/16/2024')
groupby"Error message"orderby2desc

Malheureusement, la structure des requêtes de classe est soumise aux mêmes contraintes structurelles générales que les pages du portail de gestion ; la requête ErrorList nécessite un espace de noms et une date. Il existe sûrement une meilleure approche que de faire 14 appels conjoints à cette requête de classe pour différentes dates, n'est-ce pas ? D'une certaine manière, c'est un véritable problème. S'il existe une bonne façon de procéder avec du SQL classique et que je l'ai simplement manquée, merci de me le faire savoir!

Logiquement, il convient de rédiger notre propre requête de classe personnalisée. Cela implique d'ajouter un membre de classe Query (par exemple <QueryName>) et d'implémenter des méthodes nommées <QueryName>Execute, <QueryName>Fetch et <QueryName>Close. De manière générale, la méthode Execute configure le contexte de la requête de classe et effectue toutes les tâches initiales, en conservant l'état dans qHandle. La méthode Fetch récupère une seule ligne et indique si toutes les lignes ont été trouvées ou non. Enfin, la méthode Close effectue le nettoyage final. Par exemple, si l'implémentation des méthodes Execute/Fetch utilise une variable globale privée au processus, la méthode Close peut la supprimer.

N'oubliez pas d'ajouter un indicateur [ SqlProc ] magique au membre Query afin qu'il puisse être appelé en tant que TVF (fonction table) à partir d'autres requêtes SQL!

Ci-dessous, vous trouverez un exemple complet fonctionnel:

/// Requêtes utilitaires pour aider à accéder au journal des erreurs de l'application à partir de SQLClass AppS.Util.ApplicationErrorLog
{

/// Renvoi de toutes les erreurs d'application (toutes dates confondues) à partir du journal des erreurs d'application Query All() As%Query(ROWSPEC = "Date:%Date,ErrorNumber:%Integer,ErrorMessage:%String,Username:%String") [ SqlProc ] { }

/// Récupèration d'une liste de dates comportant des erreurs et la stocke dans qHandleClassMethod AllExecute(ByRef qHandle As%Binary) As%Status { Set ns = $NamespaceNew$NamespaceSet$Namespace = "%SYS"Set stmt = ##class(%SQL.Statement).%New() Set stmt.%SelectMode = 0Set result = ##class(%SQL.Statement).%ExecDirect(stmt,"select %DLIST(""Date"") ""Dates"" from SYS.ApplicationError_DateList(?)",ns) $$$ThrowSQLIfError(result.%SQLCODE,result.%Message) If 'result.%Next(.sc) { Return sc } Set qHandle("list") = result.%Get("Dates") Set qHandle("pointer") = 0Quit$$$OK }

/// Récupèreation de la ligne suivante, en passant à la date suivante si nécessaireClassMethod AllFetch(ByRef qHandle As%Binary, ByRef Row As%List, ByRef AtEnd As%Integer = 0) As%Status [ PlaceAfter = AllExecute ] { Set sc = $$$OKSet ns = $NamespaceNew$NamespaceSet$Namespace = "%SYS"If$Get(qHandle("dateResult")) = "" { // Passage à la date suivanteSet pointer = qHandle("pointer") If '$ListNext(qHandle("list"),pointer,oneDate) { Set AtEnd = 1Quit$$$OK } Set qHandle("pointer") = pointer Set qHandle("currentDate") = oneDate Set qHandle("dateResult") = ##class(%SQL.Statement).%ExecDirect(,"select * from SYS.ApplicationError_ErrorList(?,?)",ns,oneDate) $$$ThrowSQLIfError(qHandle("dateResult").%SQLCODE,qHandle("dateResult").%Message) } If qHandle("dateResult").%Next(.sc) { // Si nous avons une ligne pour la date actuelle, ajoutons-laSet Row = $ListBuild(qHandle("currentDate"),qHandle("dateResult").%GetData(1),qHandle("dateResult").%GetData(2),qHandle("dateResult").%GetData(6)) } ElseIf$$$ISOK(sc) { // Sinon, il faut vider le jeu de résultats et appeler AllFetch pour avancerSet qHandle("dateResult") = ""Set$Namespace = ns Set sc = ..AllFetch(.qHandle,.Row,.AtEnd) } Quit sc }

ClassMethod AllClose(ByRef qHandle As%Binary) As%Status [ PlaceAfter = AllExecute ] { New$NamespaceSet$Namespace = "%SYS"// Il semble parfois nécessaire pour que %OnClose s'exécute correctementKill qHandle("dateResult") Quit$$$OK }

}

Dans cet exemple, nous commençons dans un espace de noms utilisateur, mais toutes les requêtes s'exécutent en réalité dans %SYS. Execute obtient une liste des dates d'erreur pour l'espace de noms actuel et la stocke dans qHandle. Fetch passe à la date suivante lorsque cela est approprié, puis renvoie l'erreur suivante pour la date actuelle. Et Close s'assure que la requête de classe sort de la portée dans %SYS, car j'obtenais parfois des erreurs si ce n'était pas le cas. C'était un peu surprenant, mais cela semble logique, car la requête de classe que nous appelons n'existe que dans %SYS.

La réutilisabilité des fonctions table offre de nombreuses possibilités. Par exemple, nous pouvons en ajouter une autre dans la même classe:

/// Obtenir le nombre d'erreurs survenues au cours des derniers <var>Days</var> jours
Query ErrorCounts(Days As%Integer) As%SQLQuery(ROWSPEC = "Occurrences:%Integer,ErrorMessage:%String") [ SqlProc ]
{
    SELECT COUNT(*) AS Occurrences, ErrorMessage
    FROM AppS_Util.ApplicationErrorLog_All()
    WHERE DATEDIFF(D,"Date",$h) <= :Days
    GROUP BY ErrorMessage
    ORDER BY Occurrences DESC
}

Et maintenant, pour obtenir les erreurs d'application les plus courantes au cours des 14 derniers jours, il suffit de:

call AppS_Util.ApplicationErrorLog_ErrorCounts(14)

Maintenant, il ne nous reste plus qu'à les corriger! 😅

0
0 18
Article Sylvain Guilbaud · Août 29, 2025 1m read

Rubrique FAQ InterSystems

Par défaut, l'ordre des colonnes d'une table est déterminé automatiquement par le système. Pour modifier cet ordre, définissez explicitement l'ordre de chaque propriété à l'aide du mot-clé SqlColumnNumber lors de la définition de la classe.

Exemple :

Property Name As %String [SqlColumnNumber = 2];

Veuillez consulter la documentation ci-dessous.

SqlColumnNumber

Si vous souhaitez modifier le nom de la table SQL, spécifiez SqlTableName. Si vous souhaitez modifier le nom de la colonne (nom du champ), spécifiez SqlFieldName.

0
0 16
Article Iryna Mykhailova · Août 18, 2025 4m read

Récompense d’août pour les articles sur Global Masters a retenu mon attention, et l'un des sujets proposés m'a semblé très intéressant quant à son utilisation future dans mon enseignement. Voici donc ce que j'aimerais dire à mes étudiants à propos des tables dans IRIS et de leur corrélation avec le modèle objet.

Tout d'abord, InterSystems IRIS dispose d'un modèle de données unifié. Cela signifie que lorsque vous travaillez avec des données, vous n'êtes pas enfermé dans un paradigme unique. Les mêmes données sont accessibles et manipulables comme une table SQL traditionnelle, comme un objet natif, ou même comme un tableau multidimensionnel (global). Cela signifie que lorsque vous créez une table SQL, IRIS crée automatiquement une classe d'objet correspondante. Lorsque vous définissez une classe d'objet, IRIS la rend automatiquement disponible sous forme de table SQL. Les données elles-mêmes ne sont stockées qu'une seule fois dans le moteur de stockage multidimensionnel performant d'IRIS. Le moteur SQL et le moteur objet sont simplement des « optiques » différentes pour visualiser et travailler avec les mêmes données.

Commençons par examiner la corrélation entre le modèle relationnel et le modèle objet :

Relationnel Objet
Table Classe
Colonne Propriété
Ligne Objet
Clé primaire Identifiant d'objet

La corrélation n'est pas toujours exacte, car plusieurs tables peuvent représenter une même classe, par exemple. Mais c'est une règle générale.

0
0 23
Article Iryna Mykhailova · Août 13, 2025 8m read

Au fil des ans, j'ai constaté que certaines questions SQL revenaient régulièrement au sein de la Communauté des développeurs InterSystems, notamment concernant l'utilisation du prédicat LIKE dans différents contextes. Parmi les variantes courantes, on peut citer :

et bien d'autres dérivés. J'ai donc décidé d'écrire un article consacré au fonctionnement de LIKE dans InterSystems IRIS SQL, notamment lorsqu'il est utilisé avec des variables dans Embedded SQL, Dynamic SQL et les requêtes de classes, tout en abordant l'échappement de motifs et les recherches de caractères spéciaux.

Tout d'abord, je tiens à préciser qu'InterSystems IRIS SQL offre la plupart des fonctionnalités disponibles dans d'autres bases de données relationnelles implémentant une version ultérieure de la norme SQL. Il est toutefois important de préciser qu'outre l'accès relationnel, IRIS permet également d'utiliser d'autres modèles pour obtenir les mêmes données, par exemple des modèles objet ou document.

À ce propos, examinons le prédicat LIKE et son utilisation en SQL pour la recherche de motifs.

0
0 33
Article Benjamin De Boe · Juil 30, 2025 13m read

Cet article décrit une amélioration significative apportée dans la version 2025.2 à la manière dont InterSystems IRIS traite les statistiques de table, un élément crucial pour le traitement SQL IRIS. Nous commencerons par un bref rappel sur ce que sont les statistiques de table, comment elles sont utilisées et pourquoi cette amélioration était nécessaire. Nous nous intéresserons ensuite en détail à la nouvelle infrastructure de collecte et d'enregistrement des statistiques de table, puis nous examinerons ce que ce changement signifie en pratique pour vos applications. Nous terminerons par quelques remarques supplémentaires sur les modèles rendus possibles par le nouveau modèle et nous attendons avec impatience les étapes suivantes de cette première livraison.

Je n'utilise pas SQL, pourquoi suis-je ici? – C'est une question existentielle pertinente (wink) , mais cet article peut néanmoins contenir des informations précieuses pour vous. Certaines fonctionnalités avancées d'IRIS, notamment Interopérabilité, utilisent IRIS SQL en arrière-plan, et certains changements de comportement peuvent vous inciter à activer une nouvelle tâche de maintenance. Reportez-vous à la section "Collecte automatique des statistiques des tables" ci-dessous.

Statistiques de table 101

SQL signifie Structured Query Language (langage de requête structuré). SQL est un langage dans lequel vous exprimez ce que vous voulez (la requête), plutôt que comment vous le voulez (le code permettant d'obtenir le résultat de la requête). C'est au moteur de requête d'une base de données qu'il revient d'examiner toutes les options et de choisir le plan vraisemblablement optimal pour récupérer le résultat que vous demandez. Pour déterminer le meilleur plan, l'optimiseur de requêtes a essentiellement besoin de deux choses: des informations sur la structure de votre table, telles que l'emplacement de stockage de vos données et les index disponibles, et des informations sur les données de la table elle-même: les statistiques de table. Ces statistiques de table couvrent des informations telles que la taille estimée de la table et la sélectivité de chaque champ, qui exprime la proportion moyenne de la table correspondant à une valeur de champ particulière. Ces informations sont essentielles pour prendre les bonnes décisions concernant les plans de requête. Supposons que vous deviez trouver le nombre d'utilisateurs féminins dans un code postal particulier et que vous puissiez choisir entre partir d'un index sur le sexe ou sur le code postal. La sélectivité de l'index sur le sexe sera d'environ 50 %, tandis que celle sur le code postal pourra être aussi faible que 1 % ou moins, ce qui signifie que vous filtrerez beaucoup plus rapidement l'ensemble des lignes à rechercher en partant de ce dernier. 

Si la structure des tables fait naturellement partie de votre application et peut être intégrée au code de celle-ci, ce n'est pas nécessairement le cas des statistiques de table. Si l'exemple précédent est tiré d'une petite application librairie, il est probable que les valeurs de sélectivité des champs soient valables pour toutes les librairies dans lesquelles l'application est déployée, mais s'il s'agit d'un système de dossiers médicaux électroniques, la sélectivité du champ sexe sera différente entre une maternité et un cabinet médical généraliste, et le nombre de codes postaux (et donc leur sélectivité) dépendra de la taille de la zone couverte par l'hôpital. Il est évident que vous souhaitez que vos statistiques, et donc vos plans de requête, soient basés sur les données réelles de l'environnement dans lequel l'application est déployée.

Statistiques de table dans IRIS - avant 2025.2

Sur IRIS, les statistiques de table ont toujours été stockées dans la définition d'une classe. Cela présente plusieurs inconvénients

  • Comme décrit précédemment, les distributions de données peuvent varier considérablement entre les environnements dans lesquels vous déployez votre application. Ceci n'est pas seulement vrai pour la taille estimée des tables et la sélectivité, mais encore plus pour d'autres types de statistiques plus avancées telles que les informations sur les valeurs aberrantes et les histogrammes.
  • Lorsque vous déployez une version mise à jour de votre application, vous souhaitez généralement conserver toutes les statistiques existantes, en supposant qu'elles sont basées sur les données réelles de cet environnement. Cela s'avère plus délicat lorsqu'elles sont stockées en tant que partie intégrante du code, car vous ne souhaitez évidemment pas déployer accidentellement les statistiques de table de votre environnement de développement ou de test sur le système d'un utilisateur.
  • Lorsque le code d'application est déployé sous la forme d'une base de données en lecture seule ou lorsqu'il fait partie d'une bibliothèque système IRIS (comme les messages d'interopérabilité), il n'existe aucun moyen efficace de mettre à jour les statistiques de ces tables.

Consultez également cet article précédent qui fournit davantage de détails à ce sujet. Voici certaines raisons qui nous ont poussés à repenser la gestion des statistiques de table dans IRIS. La nouvelle infrastructure est désormais incluse dans InterSystems IRIS 2025.2.

Quel est le changement?

Statistiques collectées vs statistiques fixes

Comme décrit dans les exemples précédents, le stockage des statistiques dans le code de l'application n'a de sens que dans des environnements très spécifiques et contrôlés. Dans la plupart des cas, il est préférable de conserver les statistiques avec les données à partir desquelles elles ont été collectées, plutôt que de les fixer dans le code. C'est donc ce que nous faisons dans le nouveau modèle. Nous faisons la distinction entre les statistiques collectées qui sont toujours basées sur des données réelles et stockées dans l'index d'extension (une variable globale contenant d'autres détails au format registre sur les données de votre table, également appelées extensions), et les statistiques fixes qui sont codées en dur dans la définition de classe par le développeur de l'application et peuvent être basées sur des données réelles ou sur des hypothèses raisonnables. Comme vous pouvez le deviner, les statistiques fixes correspondent au modèle antérieur à la version 2025.2 pour la gestion des statistiques de table. 

Utilisez la nouvelle commande COLLECT STATISTICS FOR TABLE t   (qui est 100 % synonyme de la commande existante TUNE TABLE , (qui est 100 % synonyme de la commande existante TUNE TABLE, et qui sert simplement à normaliser la terminologie) pour remplir un nouvel ensemble de statistiques basé sur les données actuelles de votre table. Les statistiques de table sont très petites, nous n'écrasons donc pas les statistiques précédentes, mais stockons plutôt un nouvel ensemble et conservons les anciennes statistiques à des fins d'information jusqu'à ce qu'elles répondent aux critères de purge par défaut ou soient explicitement purgées. Si vous souhaitez passer au modèle fixe, vous pouvez enregistrer les statistiques collectées dans la définition de classe à l'aide de ALTER TABLE t FIX STATISTICS. Cela peut faire partie de la procédure de package de votre application, si vous êtes certain que ces statistiques correspondent à votre environnement cible et que vous préférez le modèle statique.

Par défaut, les statistiques fixes prévalent sur les statistiques collectées. Cela garantit la rétrocompatibilité et signifie qu'en tant que développeur, c'est toujours vous qui avez le dernier mot. En fait, si vous avez des statistiques fixes, même pour un seul champ, les statistiques collectées seront ignorées et nous reviendrons à des estimations sûres basées sur le type de données du champ pour tous les champs qui n'ont pas de statistiques fixes. Si vous souhaitez tester les statistiques collectées sans supprimer vos statistiques fixes, vous pouvez inclure l'indication %NOFIXEDSTATS hint dans la clause FROM de votre texte de requête (par table) afin d'obtenir le plan de requête basé uniquement sur les statistiques collectées, ou utiliser ALTER TABLE t SET RUNTIME IGNOREFIXEDSTATS = TRUE pour définir ce comportement au niveau de la table. 

Collecte automatique des statistiques de table

L'introduction des statistiques collectées résout déjà bon nombre des inconvénients liés au packagage et au déploiement mentionnés dans l'introduction. Cependant, elle ne résout pas vraiment l'un des problèmes les plus courants rencontrés par les utilisateurs: le manque de statistiques à jour . Comme décrit dans l'introduction, des statistiques précises sont essentielles pour obtenir les meilleurs plans de requête pour votre distribution de données spécifique. Si vous ne vous êtes jamais soucié de les collecter, l'optimiseur utilisera des valeurs par défaut approximatives basées sur le type de données de vos champs, mais celles-ci sont peu susceptibles de tenir compte correctement des spécificités de votre application dans tous les cas. À partir de la version 2021.2, IRIS collectera automatiquement les statistiques pour les tables qui n'en ont pas et qui sont éligibles à une technique d'échantillonnage rapide au moment de la requête, mais cela ne se produira qu'une seule fois, et peut-être à un moment où votre table n'aura pas encore été remplie avec des données représentatives. Mais même lorsque les statistiques ont été collectées à un moment opportun, les distributions de données évoluent avec le temps (notamment les histogrammes) et nous constatons très souvent que les utilisateurs obtiennent des plans de requête sous-optimaux simplement parce qu'ils sont basés sur des statistiques obsolètes.

Avec la version 2025.2, nous introduisons une nouvelle tâche système qui s'exécute pendant une fenêtre de maintenance de nuit et qui, pour chaque espace de noms, prend en compte toutes les tables qui n'ont aucune statistique, pour lesquelles les statistiques les plus récentes ont été invalidées (par exemple après avoir modifié la définition de stockage de la table et recompilé) ou pour lesquelles au moins 25 % des données de la table ont changé depuis la dernière collecte de statistiques (environ, ceci est mesuré sur la base du ROWCOUNT combiné pour les opérations DML sur cette table). Les statistiques sont ensuite collectées pour ces tables une par une, ou jusqu'à ce que la durée maximale de la tâche de maintenance (configurable) soit atteinte. D'autres options de configuration permettent de choisir de prendre en compte les tables avec des statistiques fixes (ON par défaut), les tables mappées vers un stockage distant (OFF par défaut) et les tables qui ne sont pas éligibles pour une technique d'échantillonnage rapide (OFF par défaut). Si nécessaire, vous pouvez marquer des tables individuelles à l'aide d'un paramètre de classe SKIPAUTOMATICSTATSCOLLECTION  (ou d'un indicateur d'exécution équivalent) afin qu'elles soient ignorées par cette tâche système (notez que ce nouvel indicateur affecte également le comportement AutoTune préexistant).

Dans la version 2025.2, cette tâche système est désactivée par défaut, car nous souhaitons évaluer avec les utilisateurs l'impact de cette fonctionnalité sur les modèles d'E/S des systèmes réels. Nous encourageons les utilisateurs à activer la tâche système et à nous communiquer leur expérience en matière de charge système afin que nous puissions procéder aux ajustements nécessaires avant de l'activer par défaut dans une version ultérieure. À ce moment-là, nous prévoyons de supprimer le fonctionnement précédent d' AutoTune qui pouvait se déclencher pendant le traitement des requêtes.

La collecte manuelle des statistiques de table est bien sûr toujours prise en charge, et l'exécution de COLLECT STATISTICS après des chargements ou des purges de données importants reste une bonne pratique.

Qu'est-ce que cela signifie pour votre application?

Nous avons pris soin de concevoir le nouveau modèle afin que les applications SQL mises à niveau vers IRIS 2025.2 ne subissent aucun changement. Les statistiques préexistantes seront désormais traitées comme des statistiques fixes, qui auront priorité sur toutes les statistiques collectées automatiquement en arrière-plan. Nous conseillons aux utilisateurs qui passent au nouveau modèle de tenir compte des trois recommandations suivantes:

Suppression des statistiques fixes après la mise à niveau

Si votre application ou, en fait, n'importe quelle table avait des statistiques avant la mise à niveau (ce qui serait le cas pour toutes les tables si vous avez suivi les meilleures pratiques), envisagez de les supprimer purement et simplement. Après la mise à niveau, elles seront considérées comme des statistiques fixes et auront priorité sur toutes les statistiques que vous collecterez explicitement (peut-être via des scripts personnalisés appelant TUNE TABLE) ou implicitement. Les statistiques fixes des tables peuvent être supprimées à l'aide d'une nouvelle commande ALTER TABLE t DROP FIXED STATISTICS ou de la commande équivalente ALTER SCHEMA s DROP FIXED STATISTICS. Vous pouvez utiliser l'indication %NOFIXEDSTATS pour vérifier à l'avance l'impact sur les requêtes individuelles, selon vos préférences.

On ne conservera les statistiques fixes que si l'on estime que les statistiques prédéfinies doivent rester inchangées pour maintenir les plans de requête actuels et qu'aucune modification de la distribution des données n'est prévue.

Prise en compte des statistiques pour les classes système

Il convient de noter que le nouveau modèle de statistiques collectées s'applique aux tables dont la définition réside dans une base de données en lecture seule, y compris les tables système IRIS telles que  Ens.MessageHeader. Pour ces tables, les statistiques de table étaient auparavant peu pratiques, voire impossibles à maintenir, mais elles deviendront désormais pertinentes et, lorsque vous aurez activé la tâche du système de collecte, elles seront maintenues automatiquement. Lorsque vous utilisez des productions d'interopérabilité ou d'autres éléments de l'infrastructure IRIS pouvant impliquer SQL en arrière-plan, nous vous recommandons de surveiller les performances des opérations de recherche et autres opérations similaires après la mise à niveau, et de collecter les statistiques manuellement ou d'activer la tâche système. 

Lors de l'utilisation de la recherche de messages, nous avons constaté des améliorations significatives des performances des requêtes après l'adoption du nouveau modèle, car celui-ci pouvait désormais utiliser une sélectivité et d'autres statistiques beaucoup plus réalistes, alors qu'auparavant, il s'appuyait sur des valeurs par défaut approximatives. Nous avons donc supprimé les statistiques fixes fournies avec ces tables système.

Soyez vigilant lors de l'importation et de l'exportation entre différentes versions

Lorsque vous exportez des définitions de table avec l'indicateur /exportselectivity=1 (par défaut), les statistiques sont incluses dans un nouveau format qui prend en charge à la fois les statistiques fixes et les statistiques les plus récentes collectées collected mais qui est incompatible avec les versions antérieures. Pour prendre en charge l'importation dans des instances IRIS exécutant des versions antérieures, utilisez /exportversion=2025.1 ou /exportselectivity=0 selon le cas. Veuillez noter que les statistiques collectées et exportées à l'aide de ce format seront toujours importées en tant que statistiques collectées et ne deviendront pas fixes de manière silencieuse parce qu'elles ont été incluses dans le fichier de définition de classe export . Compte tenu de ces nuances, vous pouvez revoir votre stratégie de contrôle de source afin de vous assurer que les informations correctes sont suivies pour votre modèle de déploiement. Notez également l'indicateur symétrique /importselectivity qui peut être utilisé lors de l'importation de définitions de classe. 

Les méthodes Import() et Export() de la classe $SYSTEM.SQL.Stats.Table ont également été étendues avec un argument de type supplémentaire afin de différencier correctement les deux types de statistiques. Pour plus d'informations, consultez la référence de classe .

Travaux futurs

Cette version comprend toute l'infrastructure nécessaire pour tirer parti du nouveau modèle. Outre quelques améliorations mineures visant à faciliter l'utilisation, nous prévoyons les deux mises à jour suivantes dans une prochaine version (probablement 2025.3)

Activation de la tâche de collecte automatique

Comme indiqué précédemment, nous avons introduit une nouvelle tâche système pour la collecte automatique des statistiques des tables pendant une fenêtre de traitement par lots de nuit, mais nous l'avons désactivée afin d'éviter toute charge E/S inattendue après la mise à niveau. Dans une prochaine version, nous l'activerons par défaut, si elle n'est pas déjà activée par l'utilisateur à ce moment-là.

Taille d'échantillon plus intelligente

Nous avons remarqué que notre algorithme d'échantillonnage rapide par blocs pouvait dans certains cas surestimer la sélectivité des champs hautement sélectifs dans les grandes tables, ce qui signifie que l'optimiseur pouvait ne pas utiliser les index correspondants alors que cela aurait été optimal. Nous mettons en place un algorithme qui affinera de manière dynamique la taille de l'échantillon si nous détectons trop de variabilité entre les échantillonnages. Ce changement n'a pratiquement aucun impact sur la modification globale de l'infrastructure décrite plus haut dans cet article.

Partagez votre expérience

Cela fait longtemps que nous attendions avec impatience le déploiement de cette modification, et nous sommes ravis qu'elle soit désormais incluse dans IRIS 2025.2. Nous avons pris soin de tester cette modification dans de nombreuses configurations différentes et nous sommes convaincus que la nouvelle infrastructure est robuste, mais nous sommes conscients que les modifications peuvent affecter des pratiques de déploiement hautement personnalisées, notamment le mappage des espaces de noms et le packagage du code. Nous vous invitons donc à nous faire part de vos commentaires et espérons que la nouvelle infrastructure vous facilitera la vie.

0
0 21
Article Sylvain Guilbaud · Juil 8, 2025 3m read

Si vous migrez d'Oracle vers InterSystems IRIS, comme beaucoup de mes clients, vous risquez de rencontrer des modèles SQL spécifiques à Oracle nécessitant une conversion.

Prenons l'exemple suivant:

SELECT (TO_DATE('2023-05-12','YYYY-MM-DD') - LEVEL + 1) AS gap_date
FROM dual
CONNECT BY LEVEL <= (TO_DATE('2023-05-12','YYYY-MM-DD') - TO_DATE('2023-05-02','YYYY-MM-DD') + 1);

Dans Oracle:

  • LEVEL est une pseudo-colonne utilisée dans les requêtes hiérarchiques (CONNECT BY). Elle commence à 1 et s'incrémente de 1.
  • CONNECT BY LEVEL <= (...) détermine le nombre de lignes à générer.
  • La différence entre les deux dates plus un donne 11, donc la requête génère 11 lignes, en comptant à rebours à partir du 12 mai 2023 jusqu'au 2 mai 2023.

Répartition du résultat:

LEVEL = 1  → 2023-05-12
LEVEL = 2  → 2023-05-11
...
LEVEL = 11 → 2023-05-02

La question est maintenant de savoir comment obtenir ce résultat dans InterSystems IRIS, qui ne prend pas en charge CONNECT BY?

Une solution consiste à implémenter une requête de type SQL à l'aide d'ObjectScript qui imite ce comportement. Vous trouverez ci-dessous un exemple de définition CREATE QUERY qui accepte une date de début STARTDATE et un nombre de jours DAYS, et renvoie la liste des dates par ordre descendant.


✅ InterSystems IRIS: mise en œuvre d'une requête de l'intervalle de date

CREATE QUERY GET_GAP_DATE(IN STARTDATE DATE, IN DAYS INT)
  RESULTS (GAP_DATE DATE)
  PROCEDURE
  LANGUAGE OBJECTSCRIPT

Execute(INOUT QHandle BINARY(255), IN STARTDATE DATE, IN DAYS INT) { SET QHandle("start") = STARTDATE SET QHandle("days") = DAYS SET QHandle("level") = 1 RETURN $$$OK }

Fetch(INOUT QHandle BINARY(255), INOUT Row %List, INOUT AtEnd INT) { IF (QHandle("level") > QHandle("days")) { SET Row = "" SET AtEnd = 1 } ELSE { SET Row = $ListBuild(QHandle("start") - QHandle("level") + 1) SET QHandle("level") = QHandle("level") + 1 } RETURN $$$OK }

Close(INOUT QHandle BINARY(255)) { KILL QHandle QUIT $$$OK }

Vous pouvez exécuter la commande CREATE QUERY Vous pouvez exécuter la commande CREATE QUERY ci-dessus dans le portail IRIS System Management, ou via un outil tel que DBeaver ou un éditeur Python/Jupyter Notebook utilisant JDBC/ODBC.


🧪 Exemple d'utilisation:

Pour générer le même résultat que la requête Oracle ci-dessus, utilisez:

SELECT * FROM GET_GAP_DATE(
  TO_DATE('2023-05-12', 'YYYY-MM-DD'),
  TO_DATE('2023-05-12', 'YYYY-MM-DD') - TO_DATE('2023-05-02', 'YYYY-MM-DD') + 1
);

Cela donnera le résultat suivant:

GAP_DATE
----------
2023-05-12
2023-05-11
...
2023-05-02
(11 rows)

🔁 Utilisation avancée: Jointure avec d'autres tables

Vous pouvez également utiliser cette requête comme sous-requête ou dans des jointures:

SELECT * 
FROM GET_GAP_DATE(TO_DATE('2023-05-12', 'YYYY-MM-DD'), 11) 
CROSS JOIN dual;

Cela vous permet d'intégrer des plages de dates dans des flux SQL plus importants.


J'espère que cela sera utile à tous ceux qui sont confrontés à des scénarios de migration d'Oracle vers IRIS ! Si vous avez mis au point des solutions alternatives ou si vous proposez des améliorations, n'hésitez pas à me faire part de vos commentaires.

0
0 31
Article Sylvain Guilbaud · Mai 9, 2025 9m read

L'indication de requête parallèle augmente les performances de certaines requêtes sur les systèmes multiprocesseurs par le biais du traitement parallèle. L'optimiseur SQL détermine les cas où cela est bénéfique. Sur les systèmes à un seul processeur, cette indication n'a aucun effet.

Le traitement parallèle peut être géré par:

  1.  Définition de l'option auto parallel pour l'ensemble du système.
    
  2. L'utilisation du mot-clé %PARALLEL dans la clause FROM de certaines requêtes.
    

Le mot clé %PARALLEL est ignoré lorsqu'il est appliqué aux requêtes suivantes:

  1. Les requêtes INSERT, UPDATE et DELETE (cette fonctionnalité ne s'applique qu'aux requêtes SELECT)
  2. Les requêtes impliquant des fonctions ou des variables spécifiques au processus
  3. Une sous-requête corrélée à une requête englobante.
  4. Une sous-requête contenant des prédicats complexes, tels que les prédicats FOR SOME et FOR SOME %ELEMENT.

En plus des raisons mentionnées précédemment, voici quelques raisons pour lesquelles le traitement parallèle des requêtes peut être ignoré:

  • Certaines requêtes complexes ne bénéficient pas d'un traitement parallèle, même si elles semblent en bénéficier au départ.
  • Certaines configurations et paramètres de base de données ne supportent pas le traitement %PARALLEL.
  • Les dépendances et les relations au sein de la structure des données peuvent empêcher une parallélisation efficace.

Dans des scénarios suivants, %PARALLEL n'effectuera pas de traitement parallèle:

  1.  La requête inclut à la fois les clauses TOP et ORDER BY, en optimisant le temps le plus rapide pour atteindre la première ligne.
    
  2.  La requête fait référence à une vue et renvoie un identifiant de vue.
    
  3.  La requête utilise des formats de stockage personnalisés ou des tables GLOBAL TEMPORARY ainsi que des tables avec un stockage de référence global étendu.
    
  4.  La requête accède à une table avec une sécurité au niveau de la ligne.
    
  5.  Les données sont stockées dans une base de données distante.
    
  6.  La collation NLS au niveau du processus ne correspond pas à la collation NLS de tous les globaux impliqués.
    

Pour plus de détails sur les options, les considérations et les restrictions, reportez-vous à Configure Parallel Query Processing (Interystems Documentation) et Specify Optimization Hints in Queries (Configuration du traitement parallèle des requêtes (Documentation Interystems) et Spécifier les conseils d'optimisation dans les requêtes). Ce sujet a été récemment exploré dans le cadre d'une discussion au sein de la Communauté de développeurs d'InterSystems (DC), qui a inspiré cet article sur IRIS, Cache et Ensemble.

InterSystems IRIS supporte le traitement parallèle à la fois pour le SQL intégré, le SQL dynamique et le SQL dans les QueryMethods. Lorsque le mot-clé %PARALLEL est utilisé dans la clause FROM d'une requête pour suggérer un traitement parallèle. L'optimiseur SQL déterminera si la requête peut bénéficier d'un traitement parallèle et l'appliquera le cas échéant.

Pour utiliser efficacement le traitement %PARALLEL dans InterSystems IRIS, plusieurs paramètres et restrictions doivent être pris en compte, tant au niveau du système qu'au niveau de la requête, afin d'en tirer tous les avantages.

Dans le cas où vous essayez d'obtenir le traitement %PARALLEL à l'aide du traitement parallèle des requêtes à l'échelle du système et que le mode adaptatif est désactivé, vous pouvez activer le traitement parallèle des requêtes à l'échelle du système via le Portail de gestion ou $SYSTEM.SQL.Util.SetOption() Exemple

USER>w ##class(%SYSTEM.SQL.Util).GetOption("AutoParallel")
0
USER>d ##class(%SYSTEM.SQL.Util).SetOption("AutoParallel",1,.oldParVal)
 
USER>w ##class(%SYSTEM.SQL.Util).GetOption("AutoParallel")
1
USER>zw oldParVal
oldParVal=0

Autres aspects importants à prendre en compte lors de la mise en œuvre de la fonctionnalité %PARALLEL.

  •   Lorsque le [AdaptiveMode](https://docs.intersystems.com/iris20242/csp/docbook/DocBook.UI.Page.cls?KEY=RACS_AdaptiveMode) est activé, le traitement parallèle automatique est appliqué à toutes les requêtes SELECT, en les accompagnant de la mention %PARALLEL. Cependant, toutes les requêtes ne peuvent pas utiliser le traitement parallèle, car l'optimiseur SQL peut en décider autrement.
    
  •   Lorsque nous essayons d'utiliser cette fonctionnalité %PARALLEL, nous devons également prendre en compte le paramètre  [AutoParallelThreshold](https://docs.intersystems.com/iris20242/csp/docbook/Doc.View.cls?KEY=RACS_AutoParallelThreshold) (la valeur par défaut est 3200) et ce paramètre n'est pas utile dans le cas où [AutoParallel](https://docs.intersystems.com/iris20242/csp/docbook/DocBook.UI.Page.cls?KEY=RACS_AutoParallel) est désactivé.
    
  •   Le paramètre AutoParallelThreshold détermine si une requête est exécutée en parallèle, les valeurs les plus élevées réduisant les chances de traitement en parallèle. La valeur par défaut est 3200, elle peut être ajustée via $SYSTEM.SQL.Util.SetOption("AutoParallelThreshold",n,.oldval).
    
  •   Dans les environnements partagés, le traitement parallèle est utilisé pour toutes les requêtes, quel que soit le seuil, lorsque le mode adaptatif AdaptiveMode est activé.
    
  •   Lorsque le mode AdaptiveMode est activé (défini à 1) et que la fonctionnalité AutoParallel est désactivée, le Mode adaptatif remplace le paramètre AutoParallel et active le traitement parallèle.
    

Exemple: Exemple de classe avec 100 000 enregistrements remplis

 Class SQLClass.MyTest Extends (%Persistent, %Populate)
  {
    
    Property Name As %String(MAXLEN = 255);
    
    Property Age As %Integer(MAXVAL = 100, MINVAL = 1);
    
    Property Address As %String(MAXLEN = 255);
    
    Property City As %String(MAXLEN = 255);
    
    Property State As %String(MAXLEN = 255);
    
    Property Zip As %String(MAXLEN = 255);
    
    Property Country As %String(MAXLEN = 255);
    
    Property Comment As %String(MAXLEN = 255);
    
    Property Hobby As %String(MAXLEN = 255);
    
    Property JobTitle As %String(MAXLEN = 255);
    
    Property Company As %String(MAXLEN = 255);
    
    Property PhoneNumber As %String(MAXLEN = 255);
    
    Property Email As %String(MAXLEN = 255);
    
    Property Gender As %String(MAXLEN = 1);
    
    Property Ethnicity As %String(MAXLEN = 255);
    
    Property Race As %String(MAXLEN = 255);
    
    Property Religion As %String(MAXLEN = 255);
    
    Property MaritalStatus As %String(MAXLEN = 255);
    
    Property Children As %Integer(MAXVAL = 10, MINVAL = 0);
    
    Property Income As %Integer(MAXVAL = 100000, MINVAL = 0);
    
    Property Occupation As %String(MAXLEN = 255);
    
    Property Education As %String(MAXLEN = 255);
    
    Property HomePhone As %String(MAXLEN = 255);
    
    Property MobilePhone As %String(MAXLEN = 255);
    
    Property WorkPhone As %String(MAXLEN = 255);
    
    Property WorkEmail As %String(MAXLEN = 255);
    
    Property HomeEmail As %String(MAXLEN = 255);
    
    Property HomeAddress As %String(MAXLEN = 255);
    
    Property HomeCity As %String(MAXLEN = 255);
    
    Property HomeState As %String(MAXLEN = 255);
    
    Property HomeZip As %String(MAXLEN = 255);
    
    Property HomeCountry As %String(MAXLEN = 255);
    
    Property WorkAddress As %String(MAXLEN = 255);
    
    Property WorkCity As %String(MAXLEN = 255);
    
    Property WorkState As %String(MAXLEN = 255);
    
    Property WorkZip As %String(MAXLEN = 255);
    
    Property WorkCountry As %String(MAXLEN = 255);
    
    Property WorkPhoneNumber As %String(MAXLEN = 255);
    
    Property WorkMobilePhone As %String(MAXLEN = 255);
    
    Property WorkFax As %String(MAXLEN = 255);
    
    Property WorkWebsite As %String(MAXLEN = 255);
    
    Property WorkComments As %String(MAXLEN = 255);
    
    
    Index IdxAge On Age;
}

Test n° 1Exemple d'exécution sans % PARALLEL (pour afficher 10 000 enregistrements en SMP)

select * from SQLClass.MyTest where age>40
  • 3.2069 secondes
  • 10404 références globales
  • 3325407 commandes exécutées

Exemple d'exécution avec %PARALLEL(pour afficher 10 000 enregistrements dans SMP)

select * from %PARALLEL SQLClass.MyTest where age>40
  • 2.8681 secondes
  • 10404 références globales
  • 3325407 commandes exécutées

Test n° 2 :Exemple d'exécution sans % PARALLEL (pour afficher 1 enregistrement en SMP)

select COUNT(Children),MAX(Children),MIN(Children),AVG(Children) from SQLClass.MyTest where age>10
  • 0.4037 secondes
  • 46559 références globales
  • 1459936 commandes exécutées

Exemple d'exécution avec %PARALLEL (pour afficher 1 enregistrement en SMP)

select COUNT(Children),MAX(Children),MIN(Children),AVG(Children) from %PARALLEL SQLClass.MyTest where age>10
  • 0.0845 secondes
  • 46560 références globales
  • 1460418 commandes exécutées

Exemple avec SQL intégré

ClassMethod embeddedSQL() As %Status
{
    // w ##Class(SQLClass.MyTest).embeddedSQL()
    Set sc = $$$OK
    DO ClearBuffers^|"%SYS"|GLOBUFF()
    set stime=$p($zts,",",2)
    &sql(select COUNT(Children),MAX(Children),MIN(Children),AVG(Children) from SQLClass.MyTest where age>10)
    w:'SQLCODE "Without %Parallel : ",($p($zts,",",2)-stime),!
    DO ClearBuffers^|"%SYS"|GLOBUFF()
    set stime=$p($zts,",",2)
    &sql(select COUNT(Children),MAX(Children),MIN(Children),AVG(Children) from %PARALLEL SQLClass.MyTest where age>10)
    w:'SQLCODE "With %Parallel : ",($p($zts,",",2)-stime),!
    Return sc
}

Résultats (SQL intégré) : USER> D ##Class(SQLClass.MyTest).embeddedSQL() 5466 blocs supprimés Sans %Parallel : .355737 5217 blocs supprimés Avec %Parallel : .3407056

USER>

Exemple avec SQL dynamique

ClassMethod dynamicSQL() As %Status
{
     // w ##Class(SQLClass.MyTest).dynamicSQL()
    Set sc = $$$OK
    DO ClearBuffers^|"%SYS"|GLOBUFF()
    set stime=$p($zts,",",2), recCnt=0
    Set rs=##class(%ResultSet).%New()
    Set sc=rs.Prepare("select COUNT(Children),MAX(Children),MIN(Children),AVG(Children) from SQLClass.MyTest where age>10")
    Set sc=rs.Execute()
    While(rs.Next()) {
	 	w "COUNT(Children) : ",rs.GetData(1),"; MAX(Children) : ",rs.GetData(2),"; MIN(Children) : ",rs.GetData(3),"; AVG(Children) : ",rs.GetData(4),!
    }
    w "Without %Parallel : ",($p($zts,",",2)-stime),!!!
    DO ClearBuffers^|"%SYS"|GLOBUFF()
    set stime=$p($zts,",",2), recCnt=0
    Set sc=rs.Prepare("select COUNT(Children),MAX(Children),MIN(Children),AVG(Children) from SQLClass.MyTest where age>10")
    Set sc=rs.Execute()
    While(rs.Next()) {
	 	w "COUNT(Children) : ",rs.GetData(1),"; MAX(Children) : ",rs.GetData(2),"; MIN(Children) : ",rs.GetData(3),"; AVG(Children) : ",rs.GetData(4),!
	}
    w "With %Parallel : ",($p($zts,",",2)-stime),!
    Return sc
}

Résultats (SQL dynamique): USER>d ##Class(SQLClass.MyTest).dynamicSQL() 22163 blocs supprimés NOMBRE(Enfants) : 89908; MAX(Enfants) : 10; MIN(Enfants) : 0; AVG(Enfants) : 5.021989144458780086 Sans %Parallel : .4036913

5721 blocs supprimés NOMBRE(Enfants) : 89908; MAX(Enfants) : 10; MIN(Enfants) : 0; AVG(Enfants) : 5.021989144458780086 Avec %Parallel : .3693442

0
0 37
Article Lorenzo Scalese · Avr 30, 2025 5m read

Après tant d'années d'attente, nous avons enfin un pilote officiel disponible sur Pypi

De plus, j'ai découvert que le pilote JDBC était enfin disponible sur Maven depuis déjà 3 mois,  et le pilote .Net driver - surNuget depuis plus d'un mois.

 La mise en œuvre de la DB-API et que les fonctions devraient au moins être définies par cette norme. La seule différence devrait se situer au niveau de SQL.

Et ce qui est intéressant dans l'utilisation de bibliothèques existantes, c'est qu'elles ont déjà mis en œuvre d'autres bases de données en utilisant le standard DB-API, et que ces bibliothèques s'attendent déjà à ce que le pilote fonctionne.

J'ai décidé de tester le pilote officiel d'InterSystems en mettant en œuvre son support dans la bibliothèque SQLAlchemy-iris.

executemany

Préparez une opération de base de données (requête ou commande) et exécutez-la en fonction de toutes les séquences de paramètres ou de mappages trouvées dans la séquence seq_of_parameters.

Cette fonction très utile permet d'insérer plusieurs lignes à la fois. Commençons par un exemple simple

import iris

host = "localhost" port = 1972 namespace = "USER" username = "_SYSTEM" password = "SYS" conn = iris.connect( host, port, namespace, username, password, )

with conn.cursor() as cursor: cursor = conn.cursor()

res = cursor.execute(<span class="hljs-string">"DROP TABLE IF EXISTS test"</span>)
res = cursor.execute(
    <span class="hljs-string">"""
CREATE TABLE test (
        id IDENTITY NOT NULL,
        value VARCHAR(50)
) WITH %CLASSPARAMETER ALLOWIDENTITYINSERT = 1
"""</span>
)

cursor = conn.cursor()
res = cursor.executemany(
    <span class="hljs-string">"INSERT INTO test (id, value) VALUES (?, ?)"</span>, [
        (<span class="hljs-number">1</span>, <span class="hljs-string">'val1'</span>),
        (<span class="hljs-number">2</span>, <span class="hljs-string">'val2'</span>),
        (<span class="hljs-number">3</span>, <span class="hljs-string">'val3'</span>),
        (<span class="hljs-number">4</span>, <span class="hljs-string">'val4'</span>),
    ]
)</code></pre>

Cela fonctionne bien, mais que se passe-t-il s'il faut insérer une seule valeur par ligne.

    res = cursor.executemany(
        "INSERT INTO test (value) VALUES (?)", [
            ('val1', ),
            ('val2', ),
            ('val3', ),
            ('val4', ),
        ]
    )

Cela conduit malheureusement à une exception inattendue

RuntimeError: Cannot use list/tuple for single values (Impossible d'utiliser une liste/tuple pour des valeurs uniques)

Pour certaines raisons, une seule valeur par ligne est autorisée, et InterSystems demande d'utiliser une méthode différente

    res = cursor.executemany(
        "INSERT INTO test (value) VALUES (?)", [
            'val1',
            'val2',
            'val3',
            'val4',
        ]
    )

De cette façon, cela fonctionne bien

fetchone

Récupère la ligne suivante d'un ensemble de résultats de requête, en renvoyant une seule séquence, ou None lorsqu'il n'y a plus de données disponibles.

Un exemple simple sur sqlite

import sqlite3
con = sqlite3.connect(":memory:")

cur = con.cursor() cur.execute("SELECT 1 one, 2 two") onerow = cur.fetchone() print('onerow', type(onerow), onerow) cur.execute("SELECT 1 one, 2 two union all select '01' as one, '02' as two") allrows = cur.fetchall() print('allrows', type(allrows), allrows)

fournit

onerow <class 'tuple'> (1, 2)
allrows <class 'list'> [(1, 2), ('01', '02')]

Et avec le pilote InterSystems

import iris

con = iris.connect( hostname="localhost", port=1972, namespace="USER", username="_SYSTEM", password="SYS", )

cur = con.cursor() cur.execute("SELECT 1 one, 2 two") onerow = cur.fetchone() print("onerow", type(onerow), onerow) cur.execute("SELECT 1 one, 2 two union all select '01' as one, '02' as two") allrows = cur.fetchall() print("allrows", type(allrows), allrows)

par certaines raisons fournit

onerow <class 'iris.dbapi.DataRow'> <iris.dbapi.DataRow object at 0x104ca4e10>
allrows <class 'tuple'> ((1, 2), ('01', '02'))

Qu'est-ce que DataRow, et pourquoi ne pas utiliser un tuple ou au moins une liste

Exceptions

SLa norme décrit une variété de classes d'exceptions que le pilote est censé utiliser, au cas où quelque chose ne fonctionnerait pas. Or, le pilote InterSystems ne les utilise pas du tout, se contentant de déclencher une erreur RunTime pour toute raison, ce qui, de toute façon, est contraire à la norme.

L'application peut s'appuyer sur le type d'exception qui se produit et se comporter en conséquence. Mais le pilote InterSystems ne fournit aucune différence. Par ailleurs, SQLCODE serait utile, mais il doit être extrait du message d'erreur

Conclusion

Au cours des tests, j'ai donc trouvé plusieurs bogues

  • Erreurs aléatoires survenant à tout moment <LIST ERROR> Format de liste incorrect, type non supporté pour IRISList; Détails : type détecté : 32
    • fonctionnent correctement, si vous réessayez juste après l'erreur
  • Des erreurs de segmentation ont été détectées, je ne sais même pas comment cela se produit
  • Résultat inattendu de la fonction fetchone
  • Fonctionnement inattendu de la fonction executemany, pour une seule ligne de valeur
  • Les exceptions ne sont pas du tout implémentées, des exceptions différentes devraient être générées en cas d'erreurs différentes, et les applications s'appuient sur ces exceptions
  • Python intégré peut être interrompu en cas d'installation à côté d'IRIS
    • en raison du même nom utilisé par Python intégré et ce pilote, il remplace ce qui est déjà installé avec IRIS et peut l'interrompre

SQLAlchemy-iris supporte maintenant le pilote officiel d'InterSystems, mais ceci en raison d'une incompatibilité avec Python intégré et de plusieurs bogues découverts lors des tests. Installation à l'aide de cette commande, avec l'option définie

pip install sqlalchemy-iris[intersystems]

Et pour une utilisation simple, l'URL devrait être iris+intersystems://

from sqlalchemy import Column, MetaData, Table
from sqlalchemy.sql.sqltypes import Integer, VARCHAR
from sqlalchemy import create_engine
from sqlalchemy.orm import DeclarativeBase

DATABASE_URL = "iris+intersystems://_SYSTEM:SYS@localhost:1972/USER" engine = create_engine(DATABASE_URL, echo=True)

# Create a table metadata metadata = MetaData()

classBase(DeclarativeBase):passdefmain(): demo_table = Table( "demo_table", metadata, Column("id", Integer, primary_key=True, autoincrement=True), Column("value", VARCHAR(50)), )

demo_table.drop(engine, checkfirst=<span class="hljs-keyword">True</span>)
demo_table.create(engine, checkfirst=<span class="hljs-keyword">True</span>)
<span class="hljs-keyword">with</span> engine.connect() <span class="hljs-keyword">as</span> conn:
    conn.execute(
        demo_table.insert(),
        [
            {<span class="hljs-string">"id"</span>: <span class="hljs-number">1</span>, <span class="hljs-string">"value"</span>: <span class="hljs-string">"Test"</span>},
            {<span class="hljs-string">"id"</span>: <span class="hljs-number">2</span>, <span class="hljs-string">"value"</span>: <span class="hljs-string">"More"</span>},
        ],
    )
    conn.commit()
    result = conn.execute(demo_table.select()).fetchall()
    print(<span class="hljs-string">"result"</span>, result)

main()

En raison de bogues dans le pilote InterSystems, certaines fonctionnalités peuvent ne pas fonctionner comme prévu. J'espère que cela sera corrigé à l'avenir

0
0 27
InterSystems officiel Adeline Icard · Avr 23, 2025

Les versions de maintenance 2024.1.4 et 2023.1.6 de la plateforme de données InterSystems IRIS®, d'InterSystems IRIS® for HealthTMet de HealthShare® Health Connect sont désormais disponibles en disponibilité générale (GA). Ces versions incluent les correctifs pour l'alerte suivante récemment émise : Alerte : Requêtes SQL renvoyant des résultats erronés | InterSystems. N'hésitez pas à partager vos commentaires via la Communauté des développeurs afin que nous puissions développer ensemble un meilleur produit.

Documentation

0
0 52
Article Iryna Mykhailova · Avr 18, 2025 9m read

IRIS propose une fonctionnalité dédiée à la gestion des documents JSON, appelée DocDB.

Plateforme de données DocDB d'InterSystems IRIS® est une fonctionnalité permettant de stocker et de récupérer des données de base de données. Elle est compatible avec le stockage et la récupération de données de tables et de champs SQL traditionnels (classe et propriété), mais en est distincte. Elle est basée sur JSON (JavaScript Object Notation) qui prend en charge l'échange de données sur le Web. InterSystems IRIS prend en charge le développement de bases de données et d'applications DocDB en REST et en ObjectScript, ainsi que le support SQL pour la création ou l'interrogation de données DocDB.

De par sa nature, la base de données documentaire InterSystems IRIS est une structure de données sans schéma. Cela signifie que chaque document a sa propre structure, qui peut différer de celle des autres documents de la même base de données. Cela présente plusieurs avantages par rapport au SQL, qui nécessite une structure de données prédéfinie.

Le mot « document » est utilisé ici comme un terme technique spécifique à l'industrie, en tant que structure de stockage de données dynamique. Le « document », tel qu'utilisé dans DocDB, ne doit pas être confondu avec un document textuel ou avec la documentation.

Voyons comment DocDB peut permettre de stocker JSON dans la base de données et de l'intégrer dans des projets qui reposent uniquement sur des protocoles xDBC.

Commençons!

DocDB définit deux composants clés:

  • %DocDB.Database - Bien qu'il s'attende à la création d'une "base de données", ce qui peut prêter à confusion puisque nous avons déjà une base de données en termes SQL, il s'agit essentiellement d'une classe en ObjectScript. Pour ceux qui sont plus familiers avec SQL, elle fonctionne comme une table.
  • %DocDB.Document - Classe de base pour une 'base de données' qui étend la classe %Persistent et introduit des propriétés spécifiques à DocDB:
    • %DocumentId - IdKey
    • %Doc As %DynamicAbstractObject - Le stockage actuel du document JSON
    • %LastModified - Un horodatage mis à jour automatiquement pour chaque insertion et mise à jour

Création d'une table (base de données)

Passons maintenant à la création de notre première table, ou plutôt de notre première « base de données ». Il semble que l'on ne s'attendait pas à la création d'une base de données DocDB.Database uniquement à l'aide de SQL. Par conséquent, il n'est pas possible de créer une nouvelle « base de données » en utilisant uniquement SQL. Pour le vérifier, nous allons utiliser une approche ObjectScript classique. Voici un exemple de définition d'une classe qui étend %DocDB.Document:

Class User.docdb Extends%DocDB.Document [ DdlAllowed ]
{

}

La vérification de la table nouvellement créée à l'aide de SQL permet de s'assurer de son bon fonctionnement.

Il est temps de faire un premier essai et d'insérer quelques données

Nous pouvons insérer n'importe quelles données sans validation, ce qui signifie qu'il n'y a aucune restriction sur ce qui peut être inséré dans %Doc. La mise en place d'une validation serait bénéfique.

Extraction de valeurs d'un document

La base de données %DocDB.Database permet d'extraire des propriétés des documents et de les rendre disponibles sous forme de colonnes dédiées. Cela permet également d'effectuer une indexation sur ces propriétés.

Il faudrait d'abord obtenir la base de données.

USER>set docdb=##class(%DocDB.Database).%GetDatabase("User.docdb")

<THROW>%GetDatabase+5^%DocDB.Database.1 *%Exception.StatusException ERROR #25351: DocDB Database 'User.docdb' does not exist.

USER 2e1>w $SYSTEM.DocDB.Exists("User.docdb") 0

Euh, la base de données "n'existe pas", d'accord, créons-la alors

USER>set docdb=##class(%DocDB.Database).%CreateDatabase("User.docdb")

<THROW>%CreateDatabase+13^%DocDB.Database.1 *%Exception.StatusException ERROR #25070: The generated class name for the database 'User.docdb' conflicts with another class: User.docdb USER 2e1>

Ainsi, une simple définition de classe ne suffit pas. Il faut utiliser %DocDB.Database dès le début, ce qui n'est pas pratique, surtout lors de l'utilisation du contrôle de code source.

Pour résoudre ce problème, nous supprimons la classe existante et créons correctement la base de données:

USER>do $system.OBJ.Delete("User.docdb")

Deleting class User.docdb USER>set docdb=##class(%DocDB.Database).%CreateDatabase("User.docdb")

USER>zwrite docdb docdb=6@%DocDB.Database ; <OREF,refs=1> +----------------- general information --------------- | oref value: 6 | class name: %DocDB.Database | %%OID: $lb("3","%DocDB.Database") | reference count: 1 +----------------- attribute values ------------------ | %Concurrency = 1 <Set> | ClassName = "User.docdb" | DocumentType = "" | Name = "User.docdb" | Resource = "" | SqlNameQualified = "SQLUser.docdb" +-----------------------------------------------------

Cette fois, cela fonctionne et les données précédemment insérées restent intactes.

Supposons que nous ayons un document comme celui-ci

{"name":"test", "some_value":12345}

Extrayons ces deux champs à l'aide de la méthode %CreateProperty

USER>do docdb.%CreateProperty("name","%String","$.name",0)

USER>do docdb.%CreateProperty("someValue","%String","$.some_value",0)

Et vérifions la table

En vérifiant cette table, nous constatons que deux nouvelles colonnes ont été ajoutées, mais que celles-ci contiennent des valeurs nulles. Il semble que ces propriétés ne s'appliquent pas rétroactivement aux données existantes. Si un développeur ajoute ultérieurement des propriétés et des index à des fins d'optimisation, les données existantes ne refléteront pas automatiquement ces modifications.

Mettez à jour en utilisant la même valeur et vérifiez si %doc est json. Et nous obtenons notre valeur.

Jetons maintenant un coup d'œil à la classe, qui est entièrement créée et mise à jour par %DocDB.Database

Class User.docdb Extends%DocDB.Document [ Owner = {irisowner}, ProcedureBlock ]
{

Property name As%String [ SqlComputeCode = { set {}=$$%EvaluatePathOne^%DocDB.Document({%Doc},"$.name") }, SqlComputed, SqlComputeOnChange = %Doc ];Property someValue As%String [ SqlComputeCode = { set {}=$$%EvaluatePathOne^%DocDB.Document({%Doc},"$.some_value") }, SqlComputed, SqlComputeOnChange = %Doc ]; Index name On name; Index someValue On someValue; }

Ainsi, les propriétés créées contiennent un code pour extraire la valeur de %Doc, et oui, elles ne sont remplies que lorsque %Doc est modifié. Et des index ont été créés pour les deux champs, sans que personne ne le demande. Le fait d'avoir de nombreuses valeurs extraites augmentera l'utilisation des variables globales simplement par le nombre d'index.

Il sera possible de mettre à jour ces propriétés créées, sans nuire au %Doc original, mais les valeurs deviendront inutiles.

 
Insertion de données non valides
Insert NULL

Chaîne vide ou tout texte non-json.

Réponse franchement moche, rien à ajouter, la validation des tentatives d'insertion de quelque chose d'illégal dans une table semble raisonnable, donc, le message d'erreur serait au moins quelque chose de significatif. 

La base de données %DocDB.Database avec une méthode %GetProperty

USER>zw docdb.%GetPropertyDefinition("someValue")

{"Name":"someValue","Type":"%Library.String"}  ; <DYNAMIC OBJECT> USER>zw docdb.%GetPropertyDefinition("name")

{"Name":"name","Type":"%Library.String"}  ; <DYNAMIC OBJECT>

Le chemin d'accès à la valeur qui a été utilisé dans %CreateProperty a disparu, il n'y a aucun moyen de le valider. Si le chemin d'accès est incorrect, pour le mettre à jour, il faut d'abord appeler %DropProperty puis à nouveau %CreateProperty.

%FindDocuments

%%DocDB.Database vous permet de rechercher des documents

Pour trouver un ou plusieurs documents dans une base de données et renvoyer ceux-ci au format JSON, appelez la méthode %FindDocuments(). Cette méthode accepte n'importe quelle combinaison de trois prédicats positionnels facultatifs : une matrice de restriction, une matrice de projection et une paire clé/valeur limite.

Plus important encore, %FindDocuments ne se soucie pas de %Doc lui-même, il ne fonctionne que sur les propriétés. Assez fragile, il lève des exceptions sur tout ce qui ne correspond pas à ce qui est attendu. En fait, il construit simplement une requête SQL et l'exécute.

USER>do docdb.%FindDocuments(["firstName","B","%STARTSWITH"]).%ToJSON() 

<THROW>%FindDocuments+37^%DocDB.Database.1 *%Exception.StatusException ERROR #25541: DocDB Property 'firstName' does not exist in 'User.docdb'

USER>do docdb.%FindDocuments(["name","test","in"],["name"]).%ToJSON()

{"sqlcode":100,"message":null,"content":[{"name":"test"}]} USER>do docdb.%FindDocuments(["name","","in"],["name"]).%ToJSON()

<THROW>%FindDocuments+37^%DocDB.Database.1 *%Exception.SQL -12 -12   A term expected, beginning with either of:  identifier, constant, aggregate, $$, (, :, +, -, %ALPHAUP, %EXACT, %MVR %SQLSTRING, %SQLUPPER, %STRING, %TRUNCATE, or %UPPER^ SELECT name FROM SQLUser . docdb WHERE name IN ( )

USER>do docdb.%FindDocuments(["name","test","="]).%ToJSON()

{"sqlcode":100,"message":null,"content":[{"%Doc":"{"name":"test", "some_value":12345}","%DocumentId":"1","%LastModified":"2025-02-05 12:25:02.405"}]} USER 2e1>do docdb.%FindDocuments(["Name","test","="]).%ToJSON()

<THROW>%FindDocuments+37^%DocDB.Database.1 *%Exception.StatusException ERROR #25541: DocDB Property 'Name' does not exist in 'User.docdb'

USER>do docdb.%FindDocuments(["%Doc","JSON","IS"]).%ToJSON()

<THROW>%FindDocuments+37^%DocDB.Database.1 *%Exception.StatusException ERROR #25540: DocDB Comparison operator is not valid: 'IS' USER 2e1>do docdb.%FindDocuments(["%Doc","","IS JSON"]).%ToJSON()

<THROW>%FindDocuments+37^%DocDB.Database.1 *%Exception.StatusException ERROR #25540: DocDB Comparison operator is not valid: 'IS JSON'

L'utilisation de SQL simple serait bien plus fiable 

Enregistrement

Un autre aspect très intéressant est l'efficacité avec laquelle JSON est enregistré dans la base de données.

^poCN.bvx3.1(1)=$lb("","2025-02-05 12:25:02.405","test",12345)
^poCN.bvx3.1(1,"%Doc")="{""name"":""test"", ""some_value"":12345}"
^poCN.bvx3.1(2)=$lb("","2025-02-05 12:25:02.405")
^poCN.bvx3.1(2,"%Doc")="[1,2,3]"
^poCN.bvx3.1(3)=$lb("","2025-02-05 12:01:18.542")
^poCN.bvx3.1(3,"%Doc")="test"
^poCN.bvx3.1(4)=$lb("","2025-02-05 12:01:19.445")
^poCN.bvx3.1(4,"%Doc")=$c(0)
^poCN.bvx3.1(5)=$lb("","2025-02-05 12:01:20.794")

Le JSON est stocké sous forme de texte brut, tandis que d'autres bases de données utilisent des formats binaires pour un enregistrement et une recherche plus efficaces. La base de données DocDB d'IRIS ne prend pas en charge la recherche directe dans le contenu des documents, sauf si JSON_TABLE est utilisé, ce qui nécessite tout de même l'analyse du JSON dans un format binaire interne.

Dans la version 2025.1, %DynamicAbstractObject introduit les méthodes %ToPVA et %FromPVA, ce qui semble enregistrer le JSON dans un format binaire.

USER>do ({"name":"value"}).%ToPVA($name(^JSON.Data(1))) 

USER>zw ^JSON.Data ^JSON.Data(1,0,0)="PVA1"$c(134,0,6,0,2,0,0,0,0,0,14,0,15,0,2,0,21,9,6,136,0,1,6,0,1,0,2,1,137,0,1,5,8,1,6)"value"$c(6,0,6)"name"_$c(5)

USER>zw {}.%FromPVA($name(^JSON.Data(1)))

{"name":"value"}  ; <DYNAMIC OBJECT,refs=1>

Cependant, le traitement de certaines structures présente des incohérences.

USER>do ({}).%ToPVA($name(^JSON.Data(1)))

<SYSTEM>%ToPVA+1^%Library.DynamicAbstractObject.1

USER>do ({"name":{}}).%ToPVA($name(^JSON.Data(1)))

<SYSTEM>%ToPVA+1^%Library.DynamicAbstractObject.1

Conclusion

Actuellement, %DocDB n'est vraiment pratique qu'avec ObjectScript et a des limites en SQL. Des problèmes de performances apparaissent lorsqu'il s'agit de traiter de grands ensembles de données. Tout ce que %DocDB offre peut être réalisé en utilisant du SQL de base tout en conservant un support SQL complet. Compte tenu de l'implémentation actuelle, il y a peu d'intérêt à utiliser DocDB plutôt que des approches SQL de base.

0
0 46
InterSystems officiel Adeline Icard · Mars 27, 2025

InterSystems annonce la disponibilité générale d'InterSystems IRIS, InterSystems IRIS for Health et HealthShare Health Connect 2025.1.

La version 2025.1 de la plateforme de données InterSystems IRIS®, InterSystems IRIS® for HealthTM et HealthShare® Health Connect est désormais disponible. Il s'agit d'une version en maintenance prolongée.

Points forts de la version

Cette nouvelle version propose plusieurs nouvelles fonctionnalités et améliorations, notamment :

1. Fonctionnalités avancées de recherche vectorielle

0
0 28
Article Iryna Mykhailova · Mars 17, 2025 3m read

   

Contrairement au film mentionné dans l'image (pour ceux qui ne connaissent pas, Matrix, 1999), le choix entre Dynamic SQL et Embedded SQL n'est pas un choix entre réalité et fantaisie, mais une décision à prendre. Ci-dessous, je vais essayer de vous faciliter la tâche.

Si votre besoin concerne les interactions entre le client et l'application (et par conséquent la base de données), le Dynamic SQL peut être plus approprié, car il s'adapte très facilement à ces changements de requête. Cependant, ce dynamisme a un coût : à chaque nouvelle requête, elle est remodelée, ce qui peut entraîner un coût d'exécution plus élevé. Voici un exemple simple d'extrait de code Python.

0
0 38
InterSystems officiel Benjamin De Boe · Mars 12, 2025

Bonjour,

Nous lançons un programme d'accès anticipé pour une nouvelle fonctionnalité de partitionnement de table. Cette fonctionnalité aidera les clients IRIS à gérer des tables très volumineuses et à répartir les données de ligne et les index associés entre les bases de données et les niveaux de stockage. Le partitionnement de table est au cœur de la gestion des données relationnelles d'IRIS. Nous souhaitons donc nous assurer de la réussite de nos projets en collaborant avec quelques clients impliqués, capables de nous faire part de leurs commentaires sur les livrables initiaux et de les peaufiner si nécessaire.

Si vous travaillez avec de très grands ensembles de données relationnelles, recherchez une efficacité opérationnelle accrue et êtes prêt à tester cette nouvelle fonctionnalité, inscrivez-vous sur https://www.intersystems.com/early-access-program/. Vous recevrez un e-mail de bienvenue vous redirigeant vers le portail d'évaluation, où vous trouverez une licence de développement temporaire, des kits et des images de conteneurs récents contenant la nouvelle fonctionnalité, ainsi qu'un tutoriel pour vous aider à démarrer.

0
0 39
Question Sylvain Guilbaud · Mars 7, 2025

En utilisant IRIS 2024.1.2 lorsque je monte la base de données de routine en lecture seule, j'obtiens une erreur lors de l'exécution de requêtes SQL dynamique.

Quelles globales doivent être mappées dans une base de données en lecture-écriture afin de permettre l'écriture des plans d'exécutions ?

0
0 40
Article Rahul Singhal · Mars 3, 2025 6m read

Introduction

Pour atteindre des performances optimisées en matière d'IA, une explicabilité robuste, une adaptabilité et une efficacité dans les solutions de santé, InterSystems IRIS sert de fondation centrale pour un projet au sein du cadre multi-agent x-rAI. Cet article offre une analyse approfondie de la manière dont InterSystems IRIS permet le développement d'une plateforme d'analyse de données de santé en temps réel, permettant des analyses avancées et des informations exploitables. La solution exploite les points forts d'InterSystems IRIS, notamment le SQL dynamique, les capacités natives de recherche vectorielle, la mise en cache distribuée (ECP) et l'interopérabilité FHIR. Cette approche innovante s'aligne directement sur les thèmes du concours « Utilisation du SQL dynamique et SQL intégré », « GenAI, recherche vectorielle » et « FHIR, DME », démontrant une application pratique d'InterSystems IRIS dans un contexte critique de santé.

Architecture du système

L'Agent Santé dans x-rAI repose sur une architecture modulaire intégrant plusieurs composants :

Couche d'ingestion des données : Récupère les données de santé en temps réel à partir de dispositifs portables via l'API Terra.

Couche de stockage des données : Utilise InterSystems IRIS pour stocker et gérer les données de santé structurées.

Moteur analytique : Exploite les capacités de recherche vectorielle d'InterSystems IRIS pour l'analyse de similarité et la génération d'informations.

Couche de mise en cache : Implémente la mise en cache distribuée via le protocole Enterprise Cache Protocol (ECP) d'InterSystems IRIS pour améliorer l'évolutivité.

Couche d'interopérabilité : Utilise les normes FHIR pour s'intégrer aux systèmes externes de santé comme les DME.

Voici un diagramme d'architecture à haut niveau :

text [Dispositifs portables] --> [API Terra] --> [Ingestion des données] --> [InterSystems IRIS] --> [Moteur analytique] ------[Couche de mise en cache]------ ----[Intégration FHIR]----- Mise en œuvre technique

  1. Intégration des données en temps réel avec SQL dynamique

L'Agent Santé ingère des métriques de santé en temps réel (par exemple, fréquence cardiaque, pas effectués, heures de sommeil) depuis des dispositifs portables via l'API Terra. Ces données sont stockées dans InterSystems IRIS à l'aide du SQL dynamique pour une flexibilité dans la génération des requêtes.

Implémentation du SQL dynamique

Le SQL dynamique permet au système de construire adaptativement des requêtes basées sur les structures des données entrantes.

text def index_health_data_to_iris(data): conn = iris_connect() if conn is None: raise ConnectionError("Échec de la connexion à InterSystems IRIS.") try: with conn.cursor() as cursor: query = """ INSERT INTO HealthData (user_id, heart_rate, steps, sleep_hours) VALUES (?, ?, ?, ?) """ cursor.execute(query, ( data['user_id'], data['heart_rate'], data['steps'], data['sleep_hours'] )) conn.commit() print("Données indexées avec succès dans IRIS.") except Exception as e: print(f"Erreur lors de l'indexation des données : {e}") finally: conn.close() Avantages du SQL dynamique

Permet une construction flexible des requêtes basée sur les schémas des données entrantes.

Réduit la charge de développement en évitant les requêtes codées en dur.

Facilite l'intégration transparente de nouvelles métriques sans modifier le schéma de la base.

  1. Analytique avancée avec recherche vectorielle

Le type natif vector et les fonctions de similarité d'InterSystems IRIS ont été utilisés pour effectuer une recherche vectorielle sur les données de santé. Cela permet au système d’identifier les dossiers historiques similaires aux métriques actuelles d’un utilisateur.

Flux de travail pour la recherche vectorielle

Convertir les métriques de santé (par exemple, fréquence cardiaque, pas effectués, heures de sommeil) en une représentation vectorielle.

Stocker ces vecteurs dans une colonne dédiée dans la table HealthData.

Effectuer des recherches basées sur la similarité à l'aide de VECTOR_SIMILARITY().

Requête SQL pour la recherche vectorielle

text SELECT TOP 3 user_id, heart_rate, steps, sleep_hours, VECTOR_SIMILARITY(vec_data, ?) AS similarity FROM HealthData ORDER BY similarity DESC; Intégration Python

text def iris_vector_search(query_vector): conn = iris_connect() if conn is None: raise ConnectionError("Échec de la connexion à InterSystems IRIS.") try: with conn.cursor() as cursor: query_vector_str = ",".join(map(str, query_vector)) sql = """ SELECT TOP 3 user_id, heart_rate, steps, sleep_hours, VECTOR_SIMILARITY(vec_data, ?) AS similarity FROM HealthData ORDER BY similarity DESC; """ cursor.execute(sql, (query_vector_str,)) results = cursor.fetchall() return results except Exception as e: print(f"Erreur lors de la recherche vectorielle : {e}") return [] finally: conn.close() Avantages de la recherche vectorielle

Permet des recommandations personnalisées grâce à l’identification des tendances historiques.

Améliore l’explicabilité en reliant les métriques actuelles à des cas passés similaires.

Optimisé pour des analyses rapides grâce aux opérations SIMD (Single Instruction Multiple Data).

  1. Mise en cache distribuée pour l’évolutivité

Pour gérer efficacement le volume croissant des données, l’Agent Santé utilise le protocole Enterprise Cache Protocol (ECP) d’InterSystems IRIS. Ce mécanisme réduit la latence et améliore l’évolutivité.

Caractéristiques clés

Mise en cache locale sur les serveurs applicatifs pour minimiser les requêtes vers la base centrale.

Synchronisation automatique garantissant la cohérence entre tous les nœuds du cache.

Évolutivité horizontale permettant l’ajout dynamique de serveurs applicatifs.

Avantages du caching

Réduction des temps de réponse grâce à la mise en cache locale.

Amélioration de l’évolutivité grâce à la répartition des charges entre plusieurs nœuds.

Réduction des coûts d’infrastructure grâce à une moindre sollicitation du serveur central.

  1. Intégration FHIR pour l’interopérabilité

Le support d’InterSystems IRIS pour FHIR (Fast Healthcare Interoperability Resources) garantit une intégration fluide avec les systèmes externes comme les DME.

Flux FHIR

Les données issues des dispositifs portables sont transformées en ressources compatibles FHIR (par exemple Observation, Patient).

Ces ressources sont stockées dans InterSystems IRIS et accessibles via des API RESTful.

Les systèmes externes peuvent interroger ou mettre à jour ces ressources via des points d’accès standard FHIR.

Avantages

Assure la conformité avec les normes d’interopérabilité en santé.

Facilite un échange sécurisé des données entre systèmes.

Permet une intégration avec les flux et applications existants dans le domaine médical.

IA explicable grâce aux informations en temps réel

En combinant les capacités analytiques d’InterSystems IRIS avec le cadre multi-agent x-rAI, l’Agent Santé génère des informations exploitables et explicables. Par exemple :

« L’utilisateur 123 avait des métriques similaires (Fréquence cardiaque : 70 bpm ; Pas : 9 800 ; Sommeil : 7 h). Sur la base des tendances historiques, il est recommandé de maintenir vos niveaux actuels d’activité. »

Cette transparence renforce la confiance dans les applications IA dédiées à la santé en offrant un raisonnement clair derrière chaque recommandation.

Conclusion

L’intégration d’InterSystems IRIS dans l’Agent Santé du cadre x-rAI illustre son potentiel comme plateforme robuste pour construire des systèmes IA intelligents et explicables dans le domaine médical. En exploitant le SQL dynamique, la recherche vectorielle, la mise en cache distribuée et l’interopérabilité FHIR, ce projet fournit des informations exploitables et transparentes—ouvrant ainsi la voie à des applications IA plus fiables dans des domaines critiques comme celui de la santé.

0
0 45
InterSystems officiel Adeline Icard · Fév 20, 2025

19 février 2025 – Alerte : les requêtes SQL renvoient des résultats erronés

InterSystems a corrigé deux problèmes pouvant entraîner le renvoi de résultats erronés par un petit nombre de requêtes SQL. De plus, InterSystems a corrigé une incohérence dans la gestion des types de données date/heure qui peut entraîner des résultats différents, inattendus, mais corrects, pour les applications existantes qui s'appuient sur le comportement antérieur et incohérent.

DP-436825 : les requêtes SQL avec jointure latérale peuvent renvoyer des résultats erronés

0
0 31
Article Guillaume Rongier · Fév 7, 2025 9m read

L'essor des projets Big Data, des analyses en libre-service en temps réel, des services de recherche en ligne et des réseaux sociaux, entre autres, a donné naissance à des scénarios de requête de données massives et très performantes. En réponse à ce défi, la technologie MPP (base de données de traitement hautement parallèle) a été créée et s'est rapidement imposée. Parmi les options MPP open-source, Presto (https://prestodb.io/) est la plus connue. Cette solution a vu le jour au sein de Facebook et a été utilisée pour l'analyse de données, avant d'être mise à disposition en libre accès. Cependant, depuis que Teradata a rejoint la communauté Presto, elle offre désormais un support.

Presto se connecte aux sources de données transactionnelles (Oracle, DB2, MySQL, PostgreSQL, MongoDB et autres bases de données SQL et NoSQL) et fournit un traitement de données SQL distribué et en mémoire, combiné à des optimisations automatiques des plans d'exécution. Son objectif est avant tout d'exécuter des requêtes rapides, que vous traitiez des gigaoctets ou des téraoctets de données, en mettant à l'échelle et en parallélisant les charges de travail.

Presto n'avait pas à l'origine de connecteur natif pour la base de données IRIS, mais heureusement, ce problème a été résolu avec un projet communautaire d'InterSystems "presto-iris"(https://openexchange.intersystems.com/package/presto-iris). C'est pourquoi nous pouvons maintenant exposer une couche MPP devant les référentiels IRIS d'InterSystems pour permettre des requêtes, des rapports et des tableaux de bord de haute performance à partir de données transactionnelles dans IRIS.

Dans cet article, nous suivrons un guide étape par étape pour configurer Presto, le connecter à IRIS et établir une couche MPP pour vos clients. Nous démontrerons également les principales fonctionnalités de Presto, ses commandes et outils principaux, toujours avec IRIS en tant que base de données source.

Caractéristiques de Presto

Les caractéristiques de Presto comprennent les fonctionnalités suivantes:

  1. Architecture simple mais extensible.
  2. Connecteurs enfichables (Presto prend en charge les connecteurs enfichables pour fournir des métadonnées et des données pour les requêtes).
  3. Exécutions en pipeline (cela évite les surcharges de latence d'E/S (I/O) inutiles).
  4. Fonctions définies par l'utilisateur (les analystes peuvent créer des fonctions personnalisées définies par l'utilisateur pour faciliter la migration).
  5. Traitement en colonne vectorisé.


Avantages de Presto

Vous trouverez ci-dessous une liste des avantages offerts par Apache Presto:

Opérations SQL spécialisées;
Installation et débogage faciles;
Abstraction de stockage simple;
Évolutivité rapide des données en pétaoctets avec une faible latence.

Architecture de Presto


  • Clients: Ils sont les utilisateurs de PrestoDB. Les clients utilisent le protocole JDBC/ODBC/REST pour communiquer avec les coordinateurs.
  • Les coordinateurs: Ils sont responsables de la gestion des nœuds de travail associés, de l'analyse, du traitement des requêtes et de la génération des plans d'exécution. Ils sont également chargés de la livraison des données pour le traitement entre les opérateurs, ce qui crée des plans logiques composés d'étapes, où chaque étape est exécutée de manière distribuée à l'aide de tâches entre les opérateurs.
  • Opérateurs: Il s'agit de nœuds de calcul pour l'exécution de tâches et le traitement de données, permettant le traitement et la consommation de données à grande échelle./li>
  • Communication: Chaque travailleur Presto communique avec le coordinateur à l'aide d'un serveur de découverte pour se préparer au travail.
  • Connecteurs: Chaque type de source de données possible possède un connecteur utilisé par Presto pour consommer les données. Le projet https://openexchange.intersystems.com/package/presto-iris permet l'utilisation d'InterSystems IRIS par Presto.
  • Catalogue: Il contient des informations sur l'emplacement des données, y compris les schémas et la source de données. Lorsque les utilisateurs exécutent une instruction SQL dans Presto, ils l'exécutent contre un ou plusieurs catalogues

Cas d'utilisation de Presto

InterSystems IRIS et Presto offrent ensemble les possibilités d'utilisation suivantes:

  • Requêtes ad hoc: Vous pouvez exécuter des requêtes ad hoc très performantes sur des téraoctets de données.
  • Rapports et tableaux de bord: Il existe un moteur permettant de réaliser des requêtes de données très performantes pour les rapports, l'informatique décisionnelle en libre-service et les outils d'analyse, par exemple Apache Superset (découvrez l'exemple dans cet article).
  • Mode lac de données (Open lakehouse): Presto has the connectors and catalogs to unify required data sources and deliver scalable queries and data using SQL between workers.

InterSystems IRIS est un partenaire idéal pour Presto. Comme il s'agit d'un référentiel de données à haute performance qui supporte le traitement distribué à l'aide de shards et associé aux opérateurs Presto, n'importe quel volume de données peut être interrogé en seulement quelques millisecondes.

Installation et lancement de PrestoDB

Il y a plusieurs options (Docker et Java JAR) pour l'installation de Presto. Vous pouvez trouver plus de détails à ce sujet sur https://prestodb.io/docs/current/installation/deployment.html. Dans cet article, nous utiliserons Docker. Pour faciliter la connaissance et permettre un démarrage rapide, nous avons mis à disposition un exemple d'application sur Open Exchange (il a été dérivé d'un autre logiciel https://openexchange.intersystems.com/package/presto-iris). Suivez les étapes suivantes pour vous en faire une idée:

  1. Accédez à https://openexchange.intersystems.com/package/iris-presto-sample pour télécharger l'échantillon utilisé dans ce tutoriel.
  2. Lancer l'environnement de démonstration avec docker-compose:
    docker-compose up -d --build
    Note : Pour les besoins de la démo, il utilise Apache Superset avec superset-iris et les exemples qui l'accompagnent. Il faut donc un certain temps pour que la démonstration se télécharge.
  3. L'interface utilisateur Presto sera disponible via ce lien: http://localhost:8080/ui/#.
  4. Attendez 15 à 20 minutes (il y a beaucoup d'échantillons de données à télécharger). Lorsque SuperSet aura fini de télécharger les échantillons après 10 à 15 minutes, il devrait être disponible sur le lien http://localhost:8088/databaseview/list (saisissez admin/admin comme nom d'utilisateur/mot de passe sur la page de connexion).
  5. Accédez maintenant à la rubrique Tableaux de bord:
  6. Si nous visitons http://localhost:8080/ui, nous pouvons remarquer que Presto a exécuté des requêtes et affiche des statistiques:

Ci-dessus, vous pouvez voir l'interface web de Presto pour surveiller et gérer les requêtes. On peut y accéder à partir du numéro de port spécifié dans les propriétés de configuration du coordinateur (pour cet article, le numéro de port est 8080).

Détails sur l'exemple de code

Fichier Dockerfile

Le fichier Dockerfile est utilisé pour créer une image Docker PrestoDB avec le plugin presto-iris et le fichier JDBC InterSystems IRIS inclus:

# Image officielle de PrestoDB sur Docker HubFROM prestodb/presto

# À partir de https://github.com/caretdev/presto-iris/releases# Ajout du plugin presto-iris dans l'image DockerADDhttps://github.com/caretdev/presto-iris/releases/download/0.1/presto-iris-0.1-plugin.tar.gz /tmp/presto-iris/presto-iris-0.1-plugin.tar.gz # À partir de https://github.com/intersystems-community/iris-driver-distribution# Ajout du pilote IRIS JDBC dans l'image DockerADDhttps://raw.githubusercontent.com/intersystems-community/iris-driver-distribution/refs/heads/main/JDBC/JDK18/com/intersystems/intersystems-jdbc/3.8.4/intersystems-jdbc-3.8.4.jar /opt/presto-server/plugin/iris/intersystems-jdbc-3.8.4.jar RUN --mount=type=bind,src=.,dst=/tmp/presto-iris
tar -zxvf /tmp/presto-iris/presto-iris-0.1-plugin.tar.gz -C /opt/presto-server/plugin/iris/ --strip-components=1

Fichier Docker-compose.yml

Ce fichier crée 3 instances de conteneurs : une instance pour InterSystems IRIS (service IRIS), une instance pour PrestoDB (service Presto) et une instance pour Superset (service Superset). Le Superset est un outil de visualisation analytique utilisé pour afficher des données dans des tableaux de bord.

# à partir du projet https://github.com/caretdev/presto-irisservices:# création d'une instance de conteneur InterSystems IRIS  iris:    image:intersystemsdc/iris-community    ports:      -1972      -52773    environment:      IRIS_USERNAME:_SYSTEM      IRIS_PASSWORD:SYS# création d'une instance de conteneur PrestoDB qui utilise la base de données IRIS  presto:    build:.    volumes:# PrestoDB utilisera iris.properties pour obtenir des informations sur la connexion       -./iris.properties:/opt/presto-server/etc/catalog/iris.properties    ports:      -8080:8080# création d'une instance de conteneur Superset (Outil d'analyse du tableau de bord)  superset:    image:apache/superset:3.0.2    platform:linux/amd64    environment:      SUPERSET_SECRET_KEY:supersecret# création d'une connexion InterSystems IRIS pour le chargement des échantillons de données      SUPERSET_SQLALCHEMY_EXAMPLES_URI:iris://_SYSTEM:SYS@iris:1972/USER    volumes:      -./superset_entrypoint.sh:/superset_entrypoint.sh      -./superset_config.py:/app/pythonpath/superset_config.py    ports:      -8088:8088    entrypoint:/superset_entrypoint.sh

Fichier iris.properties

Ce fichier contient les informations nécessaires pour connecter PrestoDB à InterSystems IRIS DB et créer une couche MPP pour des requêtes performantes et évolutives à partir des tableaux de bord Superset.

# from the project https://github.com/caretdev/presto-iris
connector.name=iris
connection-url=jdbc:IRIS://iris:1972/USER
connection-user=_SYSTEM
connection-password=SYS

Fichier superset_entrypoint.sh

Ce script installe la bibliothèque superset-iris (pour le support d'IRIS par Superset), démarre l'instance Superset et charge des échantillons de données dans la base de données InterSystems IRIS. Au moment de l'exécution, les données consommées par Superset proviendront de PrestoDB, qui sera une couche MPP pour IRIS DB.

#!/bin/bash
# Installation de l'extension InterSystems IRIS Superset
pip install superset-iris

superset db upgrade

superset fab create-admin
--username admin
--firstname Superset
--lastname Admin
--email admin@superset.com
--password ${ADMIN_PASSWORD:-admin} superset init

# Téléchargement d'échantillons dans IRIS superset load-examples

# Modification de l'URI de la base de données d'échantillons en Presto superset set-database-uri -d examples -u presto://presto:8080/iris

/usr/bin/run-server.sh

Au sujet de Superset

Il s'agit d'une plateforme moderne d'exploration et de visualisation des données qui peut remplacer ou renforcer les outils propriétaires de veille stratégique pour de nombreuses équipes.Superset s'intègre parfaitement à une grande variété de sources de données.
Superset offre les avantages suivants:

  • Une interface sans code pour construire rapidement des graphiques
  • Un éditeur SQL puissant basé sur le web pour des requêtes avancées
  • Une couche sémantique légère pour définir rapidement des dimensions et des métriques personnalisées
  • Un support prêt à l'emploi pour presque toutes les bases de données SQL ou moteurs de données
  • Un large éventail de visualisations magnifiques pour présenter vos données, allant de simples diagrammes à barres à des visualisations géospatiales
  • Une couche de mise en cache légère et configurable pour alléger la charge de la base de données
  • Des options d'authentification et des rôles de sécurité très extensibles
  • Une API pour la personnalisation programmatique
  • Une architecture cloud-native conçue à partir de zéro pour s'adapter à l'échelle

Sources et supports d'apprentissage supplémentaires

  1. Tutoriel complet sur PrestoDB: https://www.tutorialspoint.com/apache_presto/apache_presto_quick_guide.htm
  2. Documentation sur PrestoDB: https://prestodb.io/docs/current/overview.html
  3. Plugin Presto-iris: https://openexchange.intersystems.com/package/presto-iris
  4. Échantillon Iris-presto: https://openexchange.intersystems.com/package/iris-presto-sample
  5. Au sujet de Superset: https://github.com/apache/superset
  6. Superset et InterSystems IRIS: https://openexchange.intersystems.com/package/superset-iris  
0
0 38
Article Iryna Mykhailova · Fév 3, 2025 2m read

Bonjour ! J'ai étendu mon référentiel de démonstration, andreas5588/demo-dbs-iris, pour faciliter le test des fonctionnalités FOREIGN SERVER et FOREIGN TABLE dans IRIS.

Pour y parvenir, j'ai créé un espace de noms appelé FEDERATION. L'idée est la suivante :

  1. Configurez des connexions JDBC pour chaque espace de noms.
  2. Créez un FOREIGN SERVER dans l'espace de noms FEDERATION pour chaque connexion.
  3. Définissez une FOREIGN TABLE au moins pour une table basée sur chaque serveur étranger.

Le script :  demo-dbs-iris/src/sql/02_create_foreign_server.sql

0
0 30