Лучший способ вставить массив Python NumPy в базу данных PostgreSQL - PullRequest
6 голосов
/ 18 февраля 2020

Наша команда использует программное обеспечение, которое сильно зависит от сброса NumPy данных в файлы, что значительно замедляет наш код. Если бы мы могли хранить наши массивы NumPy непосредственно в PostgreSQL, мы бы получили значительное повышение производительности.

Другие эффективные методы хранения массивов NumPy в любой базе данных или в структуре с возможностью поиска в базе данных, приветствуются, но PostgresSQL будет предпочтительным.

Мой вопрос очень похож на заданный ранее. Однако я ищу более надежный и производительный ответ, и я sh буду хранить любой произвольный массив NumPy.

Ответы [ 2 ]

3 голосов
/ 22 февраля 2020

Не уверен, что это то, что вам нужно, но при условии, что у вас есть доступ на чтение / запись к существующей postgres БД:

import numpy as np
import psycopg2 as psy
import pickle

db_connect_kwargs = {
    'dbname': '<YOUR_DBNAME>',
    'user': '<YOUR_USRNAME>',
    'password': '<YOUR_PWD>',
    'host': '<HOST>',
    'port': '<PORT>'
}

connection = psy.connect(**db_connect_kwargs)
connection.set_session(autocommit=True)
cursor = connection.cursor()

cursor.execute(
    """
    DROP TABLE IF EXISTS numpy_arrays;
    CREATE TABLE numpy_arrays (
        uuid VARCHAR PRIMARY KEY,
        np_array_bytes BYTEA
    )
    """
)

Суть этого подхода заключается в хранении любых numpy массив (произвольной формы и типа данных) в виде строки в таблице numpy_arrays, где uuid - уникальный идентификатор, позволяющий позднее получить массив. Фактический массив будет сохранен в столбце np_array_bytes в байтах.

Вставка в базу данных:

some_array = np.random.rand(1500,550)
some_array_uuid = 'some_array'

cursor.execute(
    """
    INSERT INTO numpy_arrays(uuid, np_array_bytes)
    VALUES (%s, %s)
    """,
    (some_array_uuid, pickle.dumps(some_array))
)

Запрос из базы данных:

uuid = 'some_array'
cursor.execute(
    """
    SELECT np_array_bytes
    FROM numpy_arrays
    WHERE uuid=%s
    """,
    (uuid,)
)
some_array = pickle.loads(cursor.fetchone()[0])

Производительность ?

Если бы мы могли хранить наши NumPy массивы непосредственно в PostgreSQL, мы бы получили значительное повышение производительности.

Я не тестировал это подход в любом случае, поэтому я не могу ни подтвердить, ни опровергнуть это ...

Дисковое пространство?

Я предполагаю, что этот подход занимает столько же дискового пространства, сколько выгрузка массивов в файл с использованием np.save('some_array.npy', some_array). Если это проблема, рассмотрите возможность сжатия байтов перед вставкой.

0 голосов
/ 21 февраля 2020

Вы можете использовать subprocess.run() для выполнения команд оболочки для массового копирования из файлов csv на сервер, используя Postgressql COPY в каналах. Я больше знаком с mssql, в котором есть метод bcp, и я не могу полностью протестировать мое решение, хотя мне кажется, что это аналогичный метод вызова через терминал. Команда терминала основана на 3-м канале с использованием метода, хотя в этом решении используется subprocess.call(), который с тех пор был обновлен с помощью subprocess.run().

https://docs.python.org/3/library/subprocess.html#subprocess .run https://ieftimov.com/post/postgresql-copy/

Python psql \ копировать CSV на удаленный сервер

import subprocess


psql_command = "\"\copy table (col1, col2) FROM file_location CSV HEADER QUOTE '\\\"' NULL ''\""
# user, hostname, password, dbname all defined elsewhere above.
command = ["psql",
    "-U", user,
    "-h", hostname,
    "-d", dbname,
    "-w", password,
    "-c", psql_command,
]

subprocess.run(command)
Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...