Лучший подход для проверки и вставки записей

Править: Для разъяснения записей первоначально прибывают из базы данных на основе плоских файлов, и не находится в базе данных MySQL.

В одной из наших существующих программ C, какая цель состоит в том, чтобы взять данные из плоского файла и вставить их (на основе критериев) в таблицу MySQL:

Open connection to MySQL DB
for record in all_record_of_my_flat_file:
  if record contain a certain field:
    if record is NOT in sql_table A: // see #1
      insert record information into sql_table A and B // see #2
Close connection to MySQL DB
  1. выберите поле из sql_table где field=XXX
  2. 2 вставляет

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

Это обычно делается каждые X месяцы для синхронизации всего или таким образом, мне говорят. Мне также сказали, что этот процесс занимает примерно несколько дней. Существует (в настоящее время) самое большее 2,5 миллиона записей (хотя не обязательно все 2.5 м будут вставлены и скорее всего намного меньше). Одна из таблицы содержит 10 полей и другие 5 полей. Нет очень, чтобы быть сделанным об итерации через записи, так как та часть не может быть изменена в данный момент. То, что я хотел бы сделать, ускоряют часть, где я запрашиваю MySQL.

Я не уверен, не учел ли я какие-либо важные детали - сообщенный мне! Я не также никакой эксперт SQL, так не стесняйтесь указывать на очевидное.

Я думал о:

  1. Помещение всех вставок в транзакцию (в данный момент я не уверен, насколько важный это для транзакции, чтобы быть категорическим или если это влияет на производительность),
  2. Использование вставляет X, где не существует Y
  3. INFILE ДАННЫХ ЗАГРУЗКИ (но это потребовало бы, чтобы я создал (возможно) большой временный файл),

Я считал, что (надо надеяться, кто-то может подтвердить), я должен отбросить индексы, таким образом, они не повторно вычисляются.

mysql Ver 14.7 Distrib 4.1.22, for sun-solaris2.10 (sparc) using readline 4.3

1
задан nevets1219 21 May 2010 в 19:09
поделиться

3 ответа

Я обсуждал с другим коллегой, и вот некоторые из улучшений, которые мы придумали:

Для:

SELECT X FROM TABLE_A WHERE Y=Z;

Изменить на (в настоящее время ожидает проверки того, является ли X и всегда ли уникален):

SELECT X FROM TABLE_A WHERE X=Z LIMIT 1;

Это было легкое изменение, и мы заметили некоторые улучшения. Я не могу точно дать количественную оценку, но я сделал:

SELECT X FROM TABLE_A ORDER BY RAND() LIMIT 1

и сравнил первые два запроса. Для нескольких тестов улучшение было примерно на 0,1 секунды. Возможно, он что-то кэшировал, но LIMIT 1 должен немного помочь.

Затем еще одно (еще не реализованное) улучшение (?):

for record number X in entire record range:
  if (no CACHE)
    CACHE = retrieve Y records (sequentially) from the database
  if (X exceeds the highest record number in cache)
    CACHE = retrieve the next set of Y records (sequentially) from the database
  search for record number X in CACHE
  ...etc

Я не уверен, что установить Y , есть ли какие-либо методы для определения числа подходящего размера, чтобы попробовать с ? В таблице 200k записей. Я отредактирую некоторые результаты, когда закончу реализацию.

0
ответ дан 3 September 2019 в 00:23
поделиться

Почему бы не обновить сервер MySQL до версии 5.0 (или 5.1), а затем использовать триггер, чтобы он всегда был актуальным (нет необходимости в ежемесячном скрипте)?

DELIMITER //
CREATE TRIGGER insert_into_a AFTER INSERT ON source_table
FOR EACH ROW 
BEGIN
    IF NEW.foo > 1 THEN
        SELECT id AS @testvar FROM a WHERE a.id = NEW.id;
        IF @testvar != NEW.id THEN
            INSERT INTO a (col1, col2) VALUES (NEW.col1, NEW.col2);
            INSERT INTO b (col1, col2) VALUES (NEW.col1, NEW.col2);
        END IF
    END IF
END //
DELIMITER ;

Затем вы даже можете настроить триггеры обновления и удаления, чтобы таблицы всегда синхронизировались (если исходная таблица col1 обновляется, она автоматически распространяется на a и b)...

1
ответ дан 3 September 2019 в 00:23
поделиться

Вот мои мысли о вашем служебном скрипте ...

1) В любом случае это просто хорошая практика, я бы сделал это, несмотря ни на что.

2) Может значительно сэкономить время выполнения. Если вы можете решить проблему в прямом SQL без использования итераций в C-программе, это может сэкономить изрядное количество времени. Сначала вам нужно профилировать его, чтобы убедиться, что он действительно работает в тестовой среде.

3) ЗАГРУЗИТЬ ДАННЫЕ INFILE - это тактика, которую нужно использовать при вставке большого количества данных. Если у вас есть много записей для вставки (я бы написал запрос, чтобы провести анализ, чтобы выяснить, сколько записей вам нужно будет вставить в таблицу B), то, возможно, вам стоит загрузить их таким образом.

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

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


РЕДАКТИРОВАТЬ: После прочтения отредактированного сообщения ваша проблемная область изменилась: у вас есть набор записей в (доступном для поиска?) Плоском файле, который вам нужно загрузить в базу данных на основе определенных критериев.Я думаю, что уловка, чтобы сделать это как можно быстрее, состоит в том, чтобы определить, где приложение C на самом деле является самым медленным и тратит больше всего времени на вращение своих пресловутых колес:

  • Если оно читает с диска, вы застряли, вы можете » Ничего не делайте с этим, если только вы не получите более быстрый диск.
  • Если он выполняет операцию вставки SQL-запроса, вы можете попробовать его оптимизировать, но вы выполняете сравнение двух баз данных (плоского файла и базы данных MySQL).

Быстрая мысль: выполняя ЗАГРУЗКУ Массовая вставка DATA INFILE для очень быстрого заполнения временной таблицы (возможно, даже таблицы в памяти, если MySQL позволяет это), а затем выполнение INSERT IF NOT EXISTS может быть быстрее, чем то, что вы делаете сейчас.

Короче говоря, проведите профилирование и выясните, где замедление. Помимо этого, поговорите с опытным администратором баз данных, чтобы узнать, как это сделать правильно.

1
ответ дан 3 September 2019 в 00:23
поделиться
Другие вопросы по тегам:

Похожие вопросы: