место Б — постгресс.
Из места А, всегда есть минимум 1 запись, которая есть в месте Б.
Я сделал скрипт который проверяет наличие записи, но чем больше записей, тем дольше работает скрипт.
Вопрос: можно ли как-то отсеивать их сразу в бд, тип, если по таким-то полям, уже есть запись, то мы её не вставляем :?
Показали бы Вы лучше код запросов и \d таблиц (или что-то, к этому близкое), а то так непонятно, IMHO.
Конкретно к чему :?
В принцыпе такая операцыя называется upsert. В postgres хорошая поддержка upsert на уровне синтаксиса insert ... on conflict, гуглите postgres upsert.
Что за "места", "скрипт который проверяет наличие записи", ну и что имеется в виду под "можно ли как-то отсеивать их сразу в бд", хотя бы.
И да, если встроенный синтаксис не подойдёт — всё равно гуглите upsert, там много вариантов решэния.
Место А — graylog Место Б — postgresql Скрипт — на питоне Данные забирает он же. Забирает данные из грэйлога, и потом вставляет их в бд. При выдаче данных с грэйлога, первая запись, чаще всего дублируется с той, что уже есть в БД (инкрементальная загрузка). Я беру максимальное значение времени из БД (Место Б), делаю запрос к месту А (грэйлог), получаю данные, и вставляю их в постгрес. Скрипт, перед тем как залить данные, проверяет каждую запись на наличие в бд, если есть, то сообщает об этом, и не улетает в пачку, когда собирается определённое кол-во записей из грэйлога (пачка), она отправляется на запись с помощью executemany
Немножко другое, мне не нужно, чтобы данные перезаписывались. Мне наоборот надо, чтобы они не попадали в бд, если уже есть
Я не хочу переписывать здесь документацыю, читайте, такой вариант там есть.
> чаще всего дублируется с той, что уже есть в БД (инкрементальная загрузка). И этот дубликат определяется по какому-то ключу, так? > Я беру максимальное значение времени из БД (Место Б), делаю запрос к месту А (грэйлог), получаю данные, и вставляю их в постгрес. О, "прекрасный" способ обновления — сколько подобного видел, и почти везде терялись данные. ;) Впрочем, может, у вас сделано "практически" правильно, не буду наговаривать... > Мне наоборот надо, чтобы они не попадали в бд, если уже есть И если есть ключ, то это INSERT ... ON CONFLICT ... DO NOTHING;. Но "сообщает об этом" так не получится — тогда нужно явно проверять и т.п.
Так, другой вопрос: БД же возвращает кол-во строк которое было задействовано :? Грубо говоря: INSERT вставил 2000 строчек :? Не знаете, он это отдаёт когда к нему обращаешься по курсору :? О, "прекрасный" способ обновления — сколько подобного видел, и почти везде терялись данные. ;) Впрочем, может, у вас сделано "практически" правильно, не буду наговаривать... Как показала практика, теряется 0, только 1 запись дублируется 🙃
> БД же возвращает кол-во строк которое было задействовано Да, возвращает (но не факт, что этот ответ все API доносят до клиента). > Как показала практика "Практика" в упоминаемых случаях тоже что-то там "показывала", но только пока либо не начинали сверять данные, либо пока не наступал "удачный" день. ;( > Мех, у меня там не уникальные ключи лежат А как Вы тогда дубликаты проверяете?
> А как Вы тогда дубликаты проверяете? Сразу по 3 полям: время, логин, и ещё одно поле. Если совпадает, то окей. Это служебные рассылки: uid, login, theme_message, time_message Где time_message — это время получение сообщения.
Ну и почему эти три поля — не ключ?
Про курсор -- не знаем, от API зависит. Но в любом случае всегда можно это через CTE обернуть в классический SELECT, и из него хоть поштучно выбирать, хоть count(*) напускать.
Разве там не указывается уникальность на таблицу :?
Где "там"? Ключ может состоять из любого количества полей, если что.
Не не, я про то, что разве это не уникальное значение на таблицу ? У меня, с одним theme_message, может быть 20к записей
Это одно уникальное сочетание значений полей на таблицу, да. Короче, почему там нет CREATE UNIQUE INDEX ON эта_таблица("время", "логин", "ещё одно поле");? ;)
Можно сделать комбинированный :?)
Да (я же его написал).
Обсуждают сегодня