Хитрый дизайн MySQL Batch - PullRequest
       8

Хитрый дизайн MySQL Batch

1 голос
/ 07 февраля 2012

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

Хитрость заключается в том, что в одном событии есть данные из трех таблиц, которые имеют ключи друг к другу. Чтобы вставить одно событие, я вставляю местоположение или получаю уже существующий идентификатор этого местоположения, затем вставляю фактический текст события и другие данные или получаю идентификатор события, если оно уже существует (некоторые повторяются еженедельно и т. Д.), И, наконец, вставляю дата с указанием местоположения и идентификаторов событий.

Я не могу использовать REPLACE INTO, потому что он потеряет старые данные с теми же ключами. Я спрашивал об этом в Tricky MySQL Batch Query , но если TLDR, то в результате я должен проверить, какие ключи уже существуют, предварительно выделить те, которые не существуют, а затем сделать одну вставку для каждой из таблиц (т.е. сделать большая часть работы в php). Это здорово, но проблема в том, что если одновременно обрабатывается более одного пакета, они оба могут выбрать предварительное распределение одних и тех же ключей, а затем перезаписать друг друга. Есть ли что-нибудь вокруг этого, потому что тогда я мог бы вернуться к этому решению? Пакеты должны работать параллельно.

Сейчас у меня есть то, что я просто отключаю индексирование на время пакета и вставляю каждое из событий отдельно, но мне нужно что-то быстрее. Любые идеи будут полезны в этой довольно сложной проблеме. (Таблицы теперь InnoDB ... могут ли транзакции помочь решить эту проблему?)

1 Ответ

1 голос
/ 07 февраля 2012

Я бы рекомендовал начать с Mysql Lock Tables , которую вы можете использовать, чтобы запретить другим сеансам запись в таблицы при вставке данных.

Например, вы можете сделать что-то подобноена это

mysql_connect("localhost","root","password");
mysql_select_db("EventsDB");
mysql_query("LOCK TABLE events WRITE");
$firstEntryIndex = mysql_insert_id() + 1;
/*Do stuff*/
...
mysql_query("UNLOCK TABLES);

Вышесказанное делает две вещи.Во-первых, он блокирует таблицу, предотвращая запись в нее других сеансов, пока вы не достигнете точки, в которой вы закончили, и не будет выполнен оператор разблокировки.Второе - это $ firstEntryIndex;которое является первым значением ключа, которое будет использоваться в любых последующих запросах вставки.

...