Задавайте вопросы, мы ответим
Вы не зашли.
Страниц: 1
Имеется логи транзакций в текстовиках. Нужно обработать логи, добавляя и изменяя пользовательские данные.
Сервер mariadb-5.5. Тип таблиц myisam. Уникальный ключ varchar(35) - идент пользователя. Кол-во пользователей порядка 20 миллионов. Для оптимизации пользователи разнесены по отдельным таблицам, индекс первый символ идента. То есть
user_a
user_b
user_c
и т.д. Таблиц порядка 120. К какой таблице обращаться для поиска или обновления данных реализовано на уровне скрипта. В таблице данных не много, текущий баланс, на сколько всего было пополнений, дата появления, последняя дата пополнения. Также дублируются все таблицы (a, b, c ...) для пользователей с отрицательным балансом.
Система linux (kubunta). Файловая ext4.
Скрипт php, коннектор mysql.
Алгоритм скрипта.
1. Получение строки из статистики и разбор. Получение первого символа идента пользователя и определение таблиц, где может быть запись.
2. Выборка из первой таблицы, с поиском по уникальному ключу (таблицы с положительным балансом).
3. Если в первой не найдено, выборка со второй таблицы (таблицы с отрицательным балансом).
4. Если пользователь не найден, то происходит вставка данных в первую таблицу.
5. Если пользователь был найден, смотрится операция и считается текущий баланс на уровне скрипта.
5.1. Если у пользователя положительный баланс и пользователь найден в первой таблице, то просто происходит обновление (update) в первой таблице используя уникальный ключ.
5.2. Если у пользователя отрицательный баланс и пользователь найден в первой таблице, то происходит вставка (insert) во вторую таблицу с обновленными данными, а из первой происходит удаление по уникальному ключу.
5.3. Если у пользователя положительный баланс и пользователь найден во второй таблице, то происходит вставка (insert) в первую таблицу с обновленными данными, а из второй происходит удаление по уникальному ключу.
5.4. Если у пользователя отрицательный баланс и пользователь найден во второй таблице, то просто происходит обновление (update) во второй таблице используя уникальный ключ.
------ Заморочка с отрицательными балансами была добавлена для оптимизации. Так как правило если пользователь уходит в минус, он уже не возвращается. А основная активность происходит с положительными балансами.
Запуск производился с нулевой базой.
Запуск скрипт показал обработку порядка 800-1000 записей в секунду. Статистика каждые 5 секунд выводится. Когда пользователей стало порядка 5-6 миллионов, то обработка упала до 500-600 транзакций. При этом была только нагрузка на диск, и то не сильно критичная.
Решено было перенести базу на ssd (твердотелый) винчестер, туда же где и установлена система. База переносилась уже с текущими пользователями. Но скорость обработки не увеличилась, то есть поднялась до предыдущих 800-1000. В принципе возврат к этим цифрам достигался и на hdd путем оптимизации таблиц. При этом нагрузки не на винчестер, ни на проце, ни на память не присутствовала.
Изменил класс работы с бд. То есть отключил физически запросы к базе. Всё остальное осталось такое же. То есть происходило по одному сценарию. Пользователь как бы искался в обоих таблицах, потом якобы происходила запись пользователя.
В таком режиме скрипт показал 18-20 к транзакций в минуту.
Тогда было решено перенести таблицы в память, создалась новая база данных с таблицами MEMORY.
Запуск скрипта. Увеличение есть, но мизерное. 900-1200 в секунду. При этом мускул работает в два потока по 50 процентов на каждом ядре, память ещё остается свободная, нагрузки на винтах нету.
Поменял прокладку php с mysql на mysqli. Изменений нет.
Поменял бд с mariadb-5.5 на мускул 5.5. Изменений нет.
Пробовал менять конфиг. И перловский оптимизатор гонял. И как предлагал pgpmyadmin устанавливал данные. И генерировал на каком-то сайте. И использовал практически девственный конфиг. Ноль реакции.
Поиск через пхпмайдами по уникальному ключу
В базе на ssd, в таблице с 500К записей. 0.0041 сек
В базе на ssd, в таблице с 1.5К записей. 0.0048 сек
Аналогичные выборки из базы с таблицами MEMORY 0.0004-0.0009.
Подумал что ключ слишком большой и сделал дополнительный на основе crc32 от идента пользователя. В таблицу загнал как int.
Брал выборку по этому ключу, а потом программно искал нужную запись в ответе от сервера. В апдейтах и делитах использовал сначала крк, а потом идент. То же не дало сильного результата.
Как разогнать этот мускул???? Хочу загрузку проца чтобы аж кипел :-)
Неактивен
А во что упираетесь-то? Сколько потоков, как нагружаете, есть ли синхронизация
внутри приложения? Ну то есть вы вливаете достаточно нагрузки, чтобы система
была нагружена?
Если вливаете, и потоков, например, тысяча, и приложение ждет, значит, уперлись
в какой-то mutex, на котором потоки синхронизируются и ждут. Какой — надо
разбираться. В случае с MyISAM и MEMORY это может быть mutex на вход в табличку. Не забудьте
про mutex перед query cache (отключаемый). Но сначала убедитесь таки в том, что
дело не в приложении, как правило, виновато именно оно.
Неактивен
Изначально лилось в один поток. Поэтому перекрещюющихся или конкурирующих запросов вообще не было.
Потом было обновление, одновременно могло работать до 5-ти потоков, в зависимости от места исполнения текущего алгоритма, и при этом потоки не конкурировали между собой, работали с разными таблицами. Дало прирост но не сильный.
На данный момент 38 миллионов записей. Пришлось ещё дробить таблицы по ранжированию. То же есть прирост местами.
Но мне не понятно одно. Что база была на простом винте, потом на твердотелом (sata3), что использовалась только память. Разницы по кол-ву обработанных строк практически не замечалось.
Да и сейчас не замечается. Изменяю алгоритм импорта, тестирую на таблицах в памяти (отдельная бд). А основной импорт происходит на ссд.
ПыСы. Начал смотреть в сторону нон sql баз. Бенчмарк аироспайка поразил, но при достижении конца память, тупо перешел в режим ридонли :-(
Неактивен
Погодите, вы делаете задачу в один поток — о каком ускорении может идти речь? Однопоточная задача в принципе не может занять больше одного ядра ведь. Ресурс, в который вы упираетесь, — количество потоков. Вы его утилизируете целиком, при этом не утилизируя другие ресурсы, которые вы мониторите.
Неактивен
Даже при однопоточном режиме задействовались два ядра (из двух) и работали два процесса (из многих) мускул на 50-70 процентов. Монтирю htop, atop и т.д. При распаралеливании процессов практически ничего не изменилось.
Неактивен
Ооок, на двух ядрах, наверное, можно и однопоточное. Давайте тогда определимся с вопросом.
Мы выяснили, что с вашим профилем нагрузки вы не упираетесь в базу данных. Поэтому смена
движка или хранилища не помогает. Так как это один поток, ни в какие mutex'ы вы тоже не упи-
раетесь. Остается: передача данных (mysql-приложение) и само приложение.
Если вопрос в том, как ускорить, то, видимо, надо профилировать приложение
Неактивен
Ну я в начале уже писал. Попытаюсь расширить.
Работа с мускульными командами вынесена в отдельный класс.
В начале старта скрипта и инициализации класса происходит коннект к базе. В данный момент инициализируется 5 копий класса. То есть 5 параллельных соединений. Но на момент последнего холостого теста, был один класс.
Неактивен
Профилировать — это найти то место, в которое упирается приложение.
Действия, которые Вы описали, мне ничего не говорят, если честно. Ну то есть аналогия
приблизительно такая: у вас есть магазин, в который вы не пустили покупателей. Вы
наблюдаете за кассиршей, и она всё время занята, совершая 18-20 тысяч операций в секунду
просмотра, нет ли покупателей в очереди в ее кассу. Профилировать нужно с покупателями:
смотреть, на что она тратит много времени, когда делает полезную работу (или обнаружить,
что она делает бесполезную, и это исключить).
Неактивен
Страниц: 1