2009-06-24 2 views
1

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

Элемент1 (целое число), Элемент2 (целое число), НСТ (Integer)

Оригинальная таблица включает в себя миллионы пар, подобных этому. и он быстро обновляется.

Чтобы сделать все это более эффективным, я хочу писать новые пары в идентичную таблицу памяти и периодически обновлять реальную таблицу на диске cron.

cron должен делать следующее: для каждой пары, если в таблице без памяти есть аналогичная пара, увеличивайте счетчик по счету из таблицы памяти. Если такая пара не существует, создайте ее со счетом из таблицы памяти.

Как я могу сделать флеш (от таблицы памяти до реальной таблицы) наиболее эффективным?

Примечания: Среда MySql 5.0.45 PHP 5.2.6 CentOS

ответ

3

Вы можете использовать INSERT ... ON DUPLICATE KEY UPDATE запрос - но это зависит от первичных ключей или UNIQUE индексов на вашей основной таблице.

INSERT 
    INTO <<master_table>> (Item1, Item2, cnt) 
    SELECT Item1, Item2, cnt FROM <<memory_table>> 
    ON DUPLICATE KEY UPDATE cnt = cnt + VALUES(cnt); 
+0

Попытка изменить мой ответ, но кажется, что, поскольку я удалил anwser и восстановил его впоследствии, SO предотвращает дальнейшее редактирование (ошибка «не найдена»; возможно, проблема кэширования). ОБНОВЛЕНИЕ КНОПКИ ON DUPLICATE должно читать ON DUPLICATE KEY UPDATE cnt = cnt + VALUES (cnt), если cnt не всегда 1 в таблице памяти. –

+0

Спасибо! оно работает. Однако мне что-то кажется странным. Решение, которое сработало для меня, - «INSERT INTO linked_items SELECT * FROM linked_items_mem как li_mem ON DUPLICATE KEY UPDATE linked_items.cnt = linked_items.cnt + li_mem.cnt;" Однако в моих тестах таблица памяти имеет 26 строк, но mysql говорит о 48 строках. Как так? – Nir

+1

@Nir: Каждая операция INSERT и UPDATE подсчитывается отдельно. В вашем случае было 26 INSERT, из которых 22 потерпели неудачу и привели к 22 UPDATE, делая 26 + 22 = 48 операций. – Quassnoi

2

Создание PRIMARY KEY на диске таблицы:

ALTER TABLE maintable ADD CONSTRAINT pk_maintable_item1_item2 (item1, item2) 

и выдает следующий запрос:

INSERT 
INTO maintable 
SELECT item1, item2, COUNT(*) AS cnt 
FROM memtable mem 
GROUP BY 
     item1, item2 
ON DUPLICATE KEY 
UPDATE cnt = maintable.cnt + mem.cnt 

Заметим, однако, что если у вас есть много DISTINCT item1, item2 пар, то solution, предложенный @S. Gehrig, скорее всего, будет работать лучше (из-за накладных расходов на GROUP BY)

+0

Мне нравится эта идея группировки строк перед вставкой. +1 –

+0

@S. Гериг: Без этого это не сработает. MySQL может обновлять каждую строку в таблице не более одного раза в рамках одного запроса на обновление, см. Это: bugs.mysql.com/bug.php?id=44494 – Quassnoi

+0

@Quassnoi: Спасибо за эту информацию. Удалил мой ответ, поскольку он не будет работать в соответствии с сообщением об ошибке выше. –

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