Я знаю, что этот вопрос задавали снова и снова. Однако это очень специфический вопрос для очень специфического сценария. Надеюсь, вы сможете мне помочь.
Я управляю базой данных журналов, содержащей около 10 таблиц. Основная таблица, в которой хранятся фактические записи журнала, содержит около 30 полей, из которых 5 доступны для поиска. Я бы сказал, что база данных в последнее время приобрела умеренный размер, поскольку мы достигли 200 миллионов записей в этой таблице. В других таблицах хранятся общие данные, из которых наибольшее имеет 4 поля с возможностью поиска, почти 1 миллион записей. Все остальные таблицы содержат менее 100 тысяч записей каждая.
Вставки входят в шипы. Я получаю журналы с предыдущего дня в (довольно плохо отформатированных) CSV-файлах каждый день в 2 часа ночи, и у меня есть до 8 часов утра, чтобы вставить их (около 20 файлов, по 100 тысяч строк каждый) в базу данных. Тогда я получаю очень мало избранных (может быть, около 1000 в день) в течение рабочего дня. Затем промыть и повторить.
Запросы SELECT довольно просты, так как они в основном состоят из одного или двух объединений с одним или двумя операторами GROUP BY. Люди, которые ищут в этой базе данных, хотят немедленных результатов, поэтому у меня есть 5 многостолбцовых индексов в основной таблице, которые помогают в точных поисках, которые у меня есть, и в настоящее время производительность SELECT довольно хорошая. Пока ни один запрос не занял более 0,1 секунды. Есть некоторые отчеты, но на их создание уходит около 10 секунд, и это приемлемо.
В настоящее время у меня есть программа на C, которую я написал для чтения данных из CSV-файлов, их очистки и вставки в виде пакетов по 1000 строк на запрос INSERT. Эти INSERT не совсем глупы, потому что мне нужно получить общие данные, посмотреть, есть ли они уже в других таблицах, вставить их, если это не так, и кэшировать их, если это так. Он также дает мне данные о производительности в виде количества записей, которые он вставляет в секунду. Эта программа довольно быстрая, и без отправки данных в базу данных я получаю около 100 тысяч строк в секунду. Конечно, эта программа и база данных находятся на одном физическом компьютере.
Теперь данные, которые я получаю каждый день, растут линейно, а производительность INSERT уменьшается логарифмически. Вчерашние данные заняли 5 с половиной часов, примерно 400 вставок строк в секунду.
Я получил некоторые контрольные данные, вставив первые 1 миллион строк с различными конфигурациями в пустую базу данных, и это почти то, что я получил:
Таблицы MyISAM: начинается со 1500 строк в секунду, логарифмически уменьшается до 700 строк в секунду к моменту вставки миллионной строки
Таблицы InnoDB: так же, как MyISAM, только на 100 строк в секунду быстрее
InnoDB со всеми индексами, отключенными в основной таблице: начинается с 2100 строк в секунду, уменьшается до 1000 строк в секунду.
InnoDB С индексами, с файловой системой, смонтированной с обратной записью данных (ext3): так же, как InnoDB, только немного, но почти незаметно быстрее.
innodb_buffer_pool_size имеет значение 1000 МБ
Избегать создания индекса не вариант, но очевидно, что он сильно влияет на производительность. Однако мне нужны гораздо более быстрые вставки. Как показывают данные, вставки будут занимать больше времени по мере роста базы данных, поэтому, поскольку данные, которые я получаю, увеличиваются с каждым днем, мне нужен огромный скачок в производительности вставки. Если бы я мог получить его до 10000 вставок в секунду или более, это было бы действительно здорово.
Системный монитор сообщает мне, что основным потреблением ресурсов является дисковый ввод-вывод, который при вставке достигает почти 100%. Из-за этого мне нужен сверхбыстрый способ вставки данных. Мой теоретический предел - это шина SATA, но это все еще довольно далеко. Кажется, что использование памяти не так высоко - около 20% (или MySQL неправильно использует память)
Для этого допустимо воссоздать базу данных в течение нескольких дней, а затем выполнить горячую замену из приложения для чтения, допустимо изменить любой параметр в ОС и MySQL, допустимо добавить память, еслитребуется.При необходимости даже можно изменить структуру базы данных.
Так что я действительно открыт для идей здесь.Кто-нибудь знает что-нибудь, что могло бы мне помочь?
Редактировать: В настоящее время я рассматриваю вопрос о вставке новых строк в таблицу MEMORY, а затем сделать SELECT INTO реальной таблицы.Надеюсь, он обновит и очистит индекс только один раз после того, как все строки были вставлены.Я попробую это в понедельник.Кто-нибудь пробовал что-то подобное раньше?