#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, чтобы решить, в какую дочернюю таблицу вставлять новые данные. Пока, похоже, все работает нормально. Поток данных поступает из посредника сообщений в виде фрагментов необработанного текста. Я обрабатываю каждый фрагмент таким образом, чтобы создавать несколько вставок (зависит от размера фрагмента). Как сейчас, мне удобнее вставлять их по одному. Если в будущем я буду экспериментировать с задержками при вставке, я рассмотрю ваше предложение о массовой вставке.