Медленная вставка в таблицу InnoDB со случайным значением столбца PRIMARY KEY - PullRequest
5 голосов
/ 26 октября 2011

Для своего сайта я использую PHP API для Flickr (http://www.flickr.com/services/api/). Этот API предоставляет несколько полезных методов для получения фотографий вокруг определенных позиций GPS.

Вызов методов API выглядит как URL с конкретными параметрами, такими как широта, долгота, ключ API, радиус, сортировка и т. Д. Скажем, это будет выглядеть как http://api.flickr.com/method?lat=0.0&lon=0.0&radius=10

Мой сайт делает более 200 000 вызовов API для создания нескольких страниц с изображениями из Flickr. Это очень сложный API, поэтому я создал кеш результатов в базе данных mySQL.

Упрощенная схема таблицы InnoDB с кешем:

char(32) request
datetime expires // 2-3 days
text     response // serialized data from API response

где request - это ПЕРВИЧНЫЙ КЛЮЧ, представляющий хэш MD5 URI запроса. Остальные поля довольно просты:)

Проблема возникает, когда таблица становится достаточно большой, например, более 100 000 строк. Новый INSERTs занимает до 2 секунд (и до 6 (!) Секунд с 1 000 000 строк).

Насколько я понимаю, проблема в том, что PRIMARY INDEX и двигатель работают на InnoDB. Каждый раз, когда вставляется новый запрос, механизм InnoDB перестраивает индекс дерева и перемещает данные, потому что MD5 (запрос) является действительно случайным значением.

Итак ... Вопрос в том, есть ли лучший способ кешировать такие запросы? Или, может быть, мне стоит перейти на движок MyISAM? Или, может быть, я должен попробовать псевдоразделение и создать несколько таблиц для решения проблемы? Или можно просто использовать не BTREE, а индекс HASH?

Любые идеи приветствуются!

Edit:

Хорошо, я попытался изменить таблицу, как предложили Фурикан и Йохан, но все же не повезло - вставка занимает до 3 секунд. В настоящее время поле request стало обычным неуникальным индексом, а новый столбец id был добавлен как ПЕРВИЧНЫЙ КЛЮЧ с автоматическим приращением. Также я попытался добавить 4 раздела в эту таблицу с одинаковыми результатами.

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

Есть еще идеи? :)

Редактировать 2:

Салман А в комментариях ниже сказал, что его аналогичная таблица работает намного лучше (~ 0,03 для вставки). Эта проблема может быть в IO нагрузки на систему. Хотя я не могу на него сильно нагрузить.

iostat Результаты:

avg-cpu:  %user   %nice %system %iowait  %steal   %idle
          22.94    0.71    8.42    8.50    0.00   59.43

Device:            tps   Blk_read/s   Blk_wrtn/s   Blk_read   Blk_wrtn
sda              38.01       151.04       114.32 1383655437 1047309046

iotop Результаты:

Total DISK READ: 152.91 K/s | Total DISK WRITE: 197.67 K/s

С MySQL на вершине списка как для записи, так и для чтения. Может быть, мои диски почти мертвы? Как я могу проверить производительность дисков?

1 Ответ

3 голосов
/ 26 октября 2011

InnoDB не поддерживает hash ключи, только Btree.

MyISAM печально известен своей ненадежностью.
Мне кажется, ваша проблема в том, что вы используете значение MD5 для первичного ключа.

Первичный ключ включен в каждый вторичный ключ.И ПК вынужден быть уникальным ключом.

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

После этого ваши вставки должны работать намного быстрее.

...