2010-05-21 6 views
1

EDIT: Чтобы прояснить записи, первоначально были получены из базы данных с плоскими файлами и не находятся в базе данных MySQL.Лучший подход к проверке и внесению записей

В одном из наших существующих программ С целью которых является принимать данные из плоских файлов и вставить их (на основе критериев) в 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 A где поле = XXX
  2. 2 вставки

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

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

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

Я думал:

  1. Собираем все вставки в сделку (на данный момент я не знаю, насколько это важно для транзакции, чтобы быть все или ничего, или если это влияет на производительность)
  2. Использование Вставка X Если не существует у
  3. LOAD DATA INFILE (но это потребовало бы создать (возможно) большой временный файл)

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

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

ответ

0

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

для:

SELECT X FROM TABLE_A WHERE Y=Z; 

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

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 к, есть ли какие-либо методы для определения того, что это хороший размерный номер попробовать с? Таблица имеет 200 тыс. Записей. В некоторых результатах я отредактирую, когда закончу реализацию.

1

Вот мои мысли о вашей полезности сценария ...

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

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

3) LOAD DATA INFILE - это тактика, используемая при вводе огромного количества данных. Если у вас много записей для вставки (я бы написал запрос для анализа, чтобы выяснить, сколько записей вам нужно будет вставить в таблицу B), тогда вам может потребоваться загрузить их таким образом.

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

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


EDIT: После прочтения вашего поста пересмотренного, ваш домен проблемы изменился: у вас есть куча записей в (для поиска?) Плоского файл, который необходимо загрузить в базу данных на основе определенных критериев. Я думаю, что трюк, чтобы сделать это как можно быстрее, чтобы определить, где приложение C на самом деле медленный и проводит большую часть времени спиннинг свои пресловутые колеса:

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

Быстрая мысль: по делая массовую вставку LOAD DATA INFILE, чтобы быстро заполнить временную таблицу (возможно, даже таблицу в памяти, если это позволяет MySQL), а затем выполнение INSERT IF NOT EXISTS может быть быстрее, чем то, что вы сейчас делаете.

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

+0

Существует около 2,5 миллионов записей (но не всех). Я могу использовать скрипт для вызова наших инструментов вместо этого и выполнять синтаксический анализ строк, но я думаю, что он будет таким же (если не медленнее). Я попытаюсь уточнить дополнительные вопросы в вопросе. – nevets1219

1

Почему бы не обновить сервер 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 обновляется, она будет автоматически распространяться на а и б) ...

+0

Я прошу прощения за то, что я не был чист, исходные данные, которые обрабатываются, НЕ находятся в базе данных (это плоский файл), поэтому я не уверен, что смогу использовать этот подход. – nevets1219

+0

Достаточно честный. Тогда это было бы невозможно вообще ... – ircmaxell

+0

Собственно, теперь, когда я думаю об этом ... Создайте временную таблицу, добавьте этот триггер, затем выполните 'LOAD DATA INFILE' ... Все« накладные расходы »сохранены прямо в БД, поэтому вы сохраняете в сети и анализируете накладные расходы ... – ircmaxell

Смежные вопросы