Интенсивная запись скользящего окна базы данных Postgresql

#sql #postgresql

#sql #postgresql

Вопрос:

У меня есть база данных, которая интенсивно записывается (непрерывный поток 50000 строк в минуту), где почти все значения вставляются одно за другим в одну таблицу. Раньше у меня была обычная база данных с одной таблицей, но таблица становилась действительно большой, а запросы занимали слишком много времени.

Теперь я разработал базу данных с подвижным окном. У меня есть родительская таблица измерений и набор дочерних таблиц meas_1, meas_2 … meas_7. В meas_1 я вставляю значения сегодняшнего дня, в meas_2 значения вчерашнего дня и так далее. Когда наступает следующий день, я создаю новую дочернюю таблицу meas_x, удаляю самую старую таблицу meas_7 и устанавливаю функцию, которая запускается при вставке данных в измерения (родительская таблица), чтобы значения перенаправлялись в meas_x (новая дочерняя таблица). Делая это, я могу воспользоваться преимуществом contraint_exclusion при запросе, и я также могу удалить самую старую таблицу (meas_7) без необходимости запускать операцию вакуумирования, чтобы освободить место на диске.

Триггер и функция выглядят следующим образом:

 CREATE TRIGGER insert_measurements_trigger 
                BEFORE INSERT ON measurements 
                FOR EACH ROW EXECUTE PROCEDURE measurements_insert_trigger();'


CREATE OR REPLACE FUNCTION measurements_insert_trigger() 
        RETURNS TRIGGER AS $$
        BEGIN
            IF ( NEW.timestamp >= d1_0 AND NEW.timestamp < d1_1 ) THEN
                INSERT INTO "meas_1" VALUES (NEW.*);
            ELSEIF ( NEW.timestamp >= d2_0 AND NEW.timestamp < d2_1 ) THEN 
                INSERT INTO "meas_2" VALUES (NEW.*); 
            ELSE 
                INSERT INTO "CatchLostRows" VALUES (NEW.*); 
            END IF; 
            RETURN NULL; 
        END; 
        $$ 
        LANGUAGE plpgsql;
  

Пожалуйста, обратите внимание, что d1_1 > d1_0 = d2_1 > d2_0

У меня есть скрипт на Python, который заботится об обновлении всех настроек в базе данных с переходящим окном. У меня есть другой скрипт на Python, отвечающий за вставку всех данных.

Моя проблема в том, что эта операция занимает слишком много времени, и я не могу справиться с такой высокой скоростью ввода. Я вставляю строки одну за другой, и поскольку функция выполняется в базовом режиме для каждой строки, это занимает много времени (это мой гость). Как я мог бы улучшить производительность моего скрипта скользящей базы данных? Было бы лучше вместо этого установить правило?

Комментарии:

1. Вы не можете заставить скрипт Python вставляться непосредственно в дочерние элементы? Это позволило бы избежать срабатывания триггера и, возможно, обеспечить эффективную массовую вставку. Без дополнительной информации, особенно в скрипте вставки Python, трудно выйти за рамки простого предположения.

2. Скрипт вставки Python выполняет следующее: 1) Считывает строку с неформатированными данными 2) Извлекает соответствующую информацию (идентификатор, значение, временную метку) 3) Вставляет соответствующую информацию (по одной строке за раз) в таблицу измерений (родительскую). Я мог бы изменить шаг 3, вставив данные в дочернюю таблицу, но у меня был бы оператор if в зависимости от времени (проверка метки времени). Я думал, что написание этих операторов if в SQL будет более эффективным / быстрым, чем в Python.

Ответ №1:

Не дорого заставить Python решить, в какой дочерний элемент он должен вставить. Я предполагаю, что есть 7 дочерних элементов, по одному на каждый день недели.

 import psycopg2
from datetime import datetime
from psycopg2.extensions import AsIs

conn = psycopg2.connect("host=localhost4 port=5432 dbname=cpn")
cursor = conn.cursor()

insert_query = """
    insert into %(child)s (id, value, "timestamp")
    values
    (%(id)s, %(value)s, %(timestamp)s)
"""
timestamp = datetime(2014, 1, 1, 0, 0, 0)
insert_dict = {
    'child': AsIs('meas_'   str(timestamp.isoweekday())),
    'id': 1,
    'value': 1,
    'timestamp': timestamp
}

cursor.execute(insert_query, insert_dict)
conn.commit()
  

Следующим шагом будет оценка некоторой формы кэширования входного потока для последующей массовой вставки. Откуда берутся данные? Как?

Комментарии:

1. Прежде всего, спасибо вам за вашу помощь. Я удалил триггер / функцию SQL и изменил сценарий вставки Python, чтобы решить, в какую дочернюю таблицу вставлять новые данные. Пока, похоже, все работает нормально. Поток данных поступает из посредника сообщений в виде фрагментов необработанного текста. Я обрабатываю каждый фрагмент таким образом, чтобы создавать несколько вставок (зависит от размера фрагмента). Как сейчас, мне удобнее вставлять их по одному. Если в будущем я буду экспериментировать с задержками при вставке, я рассмотрю ваше предложение о массовой вставке.