Article
· Déc 30, 2023 6m de lecture

Tests de performances IRIS - PostgreSQL - MySQL avec Python

Cela semble être hier lorsque nous avons réalisé un petit projet en Java pour tester les performances d'IRIS, PostgreSQL et MySQL (vous pouvez consulter l'article que nous avons écrit en juin à la fin de cet article). Si vous vous en souvenez, IRIS était supérieur à PostgreSQL et clairement supérieur à MySQL en termes d'insertions, sans grande différence en termes de requêtes.

Eh bien, peu de temps après, @Dmitry Maslennikov m'a dit "Pourquoi ne le testez-vous pas à partir d'un projet Python ?" Eh bien, voici la version Python des tests que nous avons précédemment effectués en utilisant les connexions JDBC.

Tout d'abord, sachez que je ne suis pas un expert en Python, donc si vous voyez quelque chose qui pourrait être amélioré, n'hésitez pas à me contacter.

Pour cet exemple j'ai utilisé Jupyter Notebook, qui simplifie grandement le développement Python et nous permet de voir étape par étape ce que nous faisons. Associé à cet article vous disposez de l'application pour que vous puissiez faire vos propres tests.

Avertissement pour les utilisateurs Windows

Si vous clonez le projet GitHub dans Visual Studio Code, vous devrez peut-être modifier la configuration de fin de ligne par défaut de CRLF à LF pour pouvoir déployer correctement les containers :

Si vous essayez de reproduire les tests sur vos ordinateurs, vous devez prendre en compte les éléments suivants : Docker Desktop demandera les autorisations pour accéder aux dossiers de vos ordinateurs dont il a besoin pour déployer le projet. Si vous n'avez pas configuré l'autorisation d'accès à ces dossiers avant de lancer les conteneurs Docker, la création initiale de la table de test dans PostgreSQL échouera, donc avant de lancer le projet, vous devez configurer l'accès partagé aux dossiers du projet dans votre DockerDesktop.

Pour faire cela, aller a Settings -> Resources -> File sharing et ajoutez le dossier dans lequel vous avez cloné le projet à la liste :

Vous êtes prévenu !

 

Test de performance

Pour ces tests, nous utiliserons une table assez simple contenant les informations les plus élémentaires possibles sur un patient. Ici vous pouvez voir la commande pour créer la table en SQL :

CREATE TABLE Test.Patient (
    Name VARCHAR(225),
    Lastname VARCHAR(225),
    Photo VARCHAR(5000),
    Phone VARCHAR(14),
    Address VARCHAR(225)    
)

Comme vous pouvez le voir, nous avons défini la photo du patient comme un VARCHAR(5000), la raison en est que nous allons ici inclure (théoriquement) les informations vectorisées de la photo. Il y a quelques mois, j'ai publié un article expliquant comment, grâce à Embedded Python, nous pouvions implémenter dans IRIS, un système de reconnaissance faciale. (ici) où vous pouvez voir comment les images sont transformées en vecteurs pour une comparaison ultérieure. Eh bien, le problème de la vectorisation vient du fait que ledit format vectoriel est la norme dans de nombreux modèles de Machine Learning et cela ne fait jamais de mal de tester avec quelque chose de similaire à la réalité.

 

Configuration Jupyter Notebook

Pour simplifier au maximum le développement du projet en Python, j'ai utilisé le magnifique outil Jupyter Notebook qui nous permet de développer étape par étape chacune des fonctionnalités dont nous aurons besoin.

Voici un aperçu de notre Jupyter :

Jetons un coup d'œil aux points les plus intéressants :

Librairies importées:

import iris
import names
import numpy as np
from datetime import datetime
import psycopg2
import mysql.connector
import matplotlib.pyplot as plt
import random_address
from phone_gen import PhoneNumber

Connexions aux bases de données:

IRIS:

connection_string = "iris:1972/TEST"
username = "superuser"
password = "SYS"
connectionIRIS = iris.connect(connection_string, username, password)
cursorIRIS = connectionIRIS.cursor()
print("Connected")

PostgreSQL:

connectionPostgres = psycopg2.connect(database="testuser",
                        host="postgres",
                        user="testuser",
                        password="testpassword",
                        port="5432")
cursorPostgres = connectionPostgres.cursor()
print("Connected")

MySQL:

connectionMySQL = mysql.connector.connect(
  host="mysql",
  user="testuser",
  password="testpassword"
)
cursorMySQL = connectionMySQL.cursor()
print("Connected")

Génération des valeurs a insérer

phone_number = PhoneNumber("USA")
resultsIRIS = []
resultsPostgres = []
resultsMySQL = []
parameters =  []
for x in range(1000):
    rng = np.random.default_rng()
    parameter = []
    parameter.append(names.get_first_name())
    parameter.append(names.get_last_name())
    parameter.append(str(rng.standard_normal(50)))
    parameter.append(phone_number.get_number())
    parameter.append(random_address.real_random_address_by_state('CA')['address1'])
    parameters.append(parameter)

print("Parameters built")

Insertion dans IRIS

date_before = datetime.now()

cursorIRIS.executemany("INSERT INTO Test.Patient (Name, Lastname, Photo, Phone, Address) VALUES (?, ?, ?, ?, ?)", parameters)
connectionIRIS.commit()
difference = datetime.now() - date_before
print(difference.total_seconds())
resultsIRIS.append(difference.total_seconds())

Insertion dans PostgreSQL

date_before = datetime.now()
    
cursorPostgres.executemany("INSERT INTO test.patient (name, lastname, photo, phone, address) VALUES (%s,%s,%s,%s,%s)", parameters)
connectionPostgres.commit()
difference = datetime.now() - date_before
print(difference.total_seconds())
resultsPostgres.append(difference.total_seconds())

Insertion dans MySQL

date_before = datetime.now()
    
cursorMySQL.executemany("INSERT INTO test.patient (name, lastname, photo, phone, address) VALUES (%s,%s,%s,%s,%s)", parameters)
connectionMySQL.commit()
difference = datetime.now() - date_before
print(difference.total_seconds())
resultsMySQL.append(difference.total_seconds())

Pour notre test, j'ai décidé d'insérer l'ensemble de valeurs suivant pour chaque base de données :

  • 1 insertion avec 1000 patients.
  • 1 insertion avec 5000 patients.
  • 1 insertion avec 20,000 patients.
  • 1 insertion avec 50,000 patients.

Gardez à l’esprit lors de l’exécution des tests que le temps passé le plus longtemps est la création des valeurs à insérer par Python. Pour se rapprocher de la réalité, j'ai lancé plusieurs tests en amont pour que les bases disposent déjà d'un ensemble d'enregistrements important (environ 200 000 enregistrements).

Résultats des tests

Insertion de 1000 patients:

  • InterSystems IRIS: 0.037949 seconds.
  • PostgreSQL: 0.106508 seconds.
  • MySQL: 0.053338 seconds.

Insertion de 5,000 patients:

  • InterSystems IRIS: 0.162791 seconds.
  • PostgreSQL: 0.432642 seconds.
  • MySQL: 0.18925 seconds.

Insertion de 20,000 patients:

  • InterSystems IRIS: 0.601944 seconds.
  • PostgreSQL: 1.803113 seconds.
  • MySQL: 0.594396 seconds.

Insertion de 50,000 patients:

  • InterSystems IRIS: 1.482824 seconds.
  • PostgreSQL: 4.581251 seconds.
  • MySQL: 2.162996 seconds.

Bien qu'il s'agisse d'un test assez simple, il est très significatif puisqu'il nous permet de voir la tendance de chaque base de données en termes de performances d'insertion.

Conclusions

Si nous comparons les performances des tests effectués avec le projet Java et celui actuel en Python, nous verrons qu'à cette occasion le comportement de PostgreSQL est clairement inférieur au projet Python, étant 4 fois plus lent qu'InterSystems IRIS,  tandis que MySQL a été amélioré par rapport à la version Java.

Incontestablement, InterSystems IRIS reste le meilleur des trois, avec un comportement plus linéaire et de meilleures performances d'insertion, quelle que soit la technologie utilisée.

Caractéristiques techniques de l'ordinateur portable utilisé pour les tests :

  • Système d'exploitation: Microsoft Windows 11 Pro.
  • Processeur: 13th Gen Intel(R) Core(TM) i9-13900H, 2600 Mhz.
  • RAM: 64 GB.
Discussion (0)1
Connectez-vous ou inscrivez-vous pour continuer