Artículo
· 29 dic, 2023 Lectura de 6 min

Pruebas de rendimiento IRIS - PostgreSQL y MySQL mediante Python

Parece que fue ayer cuando hicimos un pequeño proyecto en Java para probar el rendimiento de IRIS, PostgreSQL y MySQL (podéis revisar el artículo que escribimos allá por Junio al final de este artículo). Si recordáis IRIS se mostró superior a PostgreSQL y claramente superior a MySQL en las inserciones, no habiendo gran diferencia en las consultas.

Poco después @Dmitry Maslennikov me dijo "¿Por qué no pruebas desde un proyecto en Python?" pues bien, aquí está la versión en Python de las pruebas que realizamos mediante las conexiones JDBC previamente.

Antes que nada avisaros de que no soy un experto en Python, por lo que si véis cualquier cosa que se pueda mejorar, no dudéis en poneros en contacto conmigo.

Para este ejemplo he hecho uso de Jupyter Notebook que simplifica de sobremanera el desarrollo de Python y nos permite ir viendo paso a paso lo que vamos haciendo. Asociado a este artículo tenéis la aplicación para que podáis hacer vuestra propias pruebas.

Aviso previo para usuarios de Windows

Si clonais el proyecto de GitHub en Visual Studio Code posiblemente tengáis que cambiar la configuración del fin de línea por defecto de CRLF a LF para poder desplegar correctamente los contenedores:

Si vais a intentar reproducir las pruebas en vuestros equipos debéis tener en consideración lo siguiente, Docker Desktop solicitará permisos para acceder a las carpetas de vuestros equipos que necesita para desplegar el proyecto. Si no habéis configurado el permiso de acceso a estas carpetas antes de lanzar los contenedores de Docker la creación inicial de la tabla de pruebas en PostgreSQL fallará, por lo que antes de lanzar el proyecto deberéis configurar el acceso compartido a las carpetas del proyecto en vuestro Docker Desktop.

Para ello deberéis acceder a Settings -> Resources -> File sharing y añadir a la lista la carpeta donde habéis clonado el proyecto:

¡Avisados estáis!

 

Pruebas de rendimiento

Para estas pruebas usaremos una tabla bastante simple con la información más básica posible de un paciente aquí podéis ver en SQL el comando de creación de la tabla:

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

Como véis tenemos definida a la foto del paciente como un VARCHAR(5000), el motivo de ello es porque aquí vamos a incluir (teóricamente) la información vectorizada de la foto, hace unos meses publiqué un artículo explicando como mediante Embedded Python podíamos implementar en IRIS un sistema de reconocimiento facial (aquí) donde podéis ver como se transforman las imágenes en vectores para su posterior comparación. Pues bien, el tema de la vectorización viene dada por el hecho de que dicho formato vectorial es la norma en multitud de modelos de Machine Learning y nunca está de más hacer las pruebas con algo parecido a la realidad (sólo algo).

 

Configuración de Jupyter Notebook

Para simplificar al máximo el desarrollo del proyecto en Python he usado la magnífica herramienta de Jupyter Notebook que nos permite ir desarrollando paso a paso cada una de las funcionalidades que necesitaremos.

Aquí tenéis un vistazo de nuestro Jupyter:

Echemos un vistazo a los puntos más interesantes del mismo:

Importación de librerías:

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

Conectando con las bases de datos:

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")

Generación de los valores a insertar

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")

Inserción en 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())

Inserción en 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())

Inserción en 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())

 

Para nuestra prueba he decidido insertar los siguientes conjunto de valores para cada base de datos:

  • 1 inserción con 1000 pacientes.
  • 1 inserción con 5000 pacientes.
  • 1 inserción con 20000 pacientes.
  • 1 inserción con 50000 pacientes.

Tened en cuenta a la hora de realizar las pruebas que el mayor tiempo empleado es el de la creación por parte de Python de los valores a insertar. Para acercarlo más a la realidad he lanzado varias pruebas con anterioridad para que las bases de datos tengan ya un conjunto de registros significativo (entorno a 200.000 registros).

Resultado de las pruebas

Inserción de 1000 pacientes:

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

Inserción de 5000 pacientes:

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

Inserción de 20000 pacientes:

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

Inserción de 50000 pacientes:

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

Si bien esta es una prueba bastante simple es muy significativa ya que nos permite ver la tendencia de cada base de datos respecto al rendimiento en las inserciones.

Conclusiones

Si comparamos el rendimiento en las pruebas realizada con el proyecto de Java y el actual en Python veremos que en esta ocasión el comportamiento de PostgreSQL es claramente inferior para el proyecto de Python siendo 4 veces más lento que InterSystems IRIS,  mientras que MySQL ha mejorado respecto a la versión en Java.

Indiscutiblemente InterSystems IRIS sigue siendo la mejor de las tres, con un comportamiento más lineal y un mejor rendimiento en las inserciones, independientemente de la tecnología utilizada.

Características técnicas del portatil utilizado para las pruebas:

  • Operative System: Microsoft Windows 11 Pro.
  • Processor: 13th Gen Intel(R) Core(TM) i9-13900H, 2600 Mhz.
  • RAM: 64 GB.
Comentarios (2)1
Inicie sesión o regístrese para continuar

He creado una nueva rama en el proyecto de GitHub para incluir la prueba de Oracle. No lo voy a incluir en la rama de main porque requiere ampliar la memoria asignada a docker porque Oracle consume recursos como una mala bestia... Pero los que queráis probarla aquí tenéis la rama:

https://github.com/intersystems-ib/workshop-py-performance/tree/oracle

Aquí podéis ver la gráfica comparativa incluyendo a Oracle

Como podéis ver tanto Oracle como IRIS son equivalentes en términos de rendimiento.