Php - оптимизация нескольких приращений счетчика

На сервере LAMP с очень интенсивным трафиком я использую таблицу памяти для отслеживания нескольких элементов данных в качестве счетчиков. Это реализовано так:

$query = "INSERT INTO daily_info_mem SET di_num=1 ,di_type=9, di_date = current_date(), di_sid= $sid_int ,di_name='user_counter' ON DUPLICATE KEY UPDATE di_num=di_num+1";

Индекс устанавливает уникальный di_type и дату, поэтому, если счетчик существует для этой даты, то di_type увеличивается, если нет, создается строка для этой даты и типа данных со значением 0.

Таких запросов несколько для каждого просмотра страницы. Это означает несколько вызовов mysql.

Можно ли максимально оптимизировать это в один вызов mysql, который будет обновлять несколько произвольных счетчиков и при этом сохранять идею создания строки при необходимости или увеличения значения, если оно существует?


person Nir    schedule 08.09.2009    source источник
comment
Почему бы вам не использовать автоинкремент и тому подобное для обработки вашего счетчика?   -  person Clement Herreman    schedule 08.09.2009
comment
Если я прав, автоинкремент предназначен для значений индекса на уровне строки. Я увеличиваю поле, а не количество строк   -  person Nir    schedule 08.09.2009
comment
Вы имеете в виду поля счетчика в одной строке? Например, ON DUPLICATE KEY UPDATE di_num=di_num+1, c2=c2+99, c3=c3+47 ?   -  person VolkerK    schedule 08.09.2009
comment
да. пожалуйста, посмотрите код в вопросе   -  person Nir    schedule 08.09.2009


Ответы (1)


Я бы рекомендовал полностью переосмыслить этот тип запроса. Вы часто используете свою основную базу данных для чего-то, что можно было бы лучше обрабатывать в памяти. Обязательно ли каждый раз мгновенно обновлять MySQL? Если вы можете получить его из MySQL и в memcached, вы увидите огромный скачок производительности, и вы всегда можете запустить скрипт в фоновом режиме, чтобы сопоставлять данные и регулярно отправлять их в MySQL (скажем, каждые 5 минут), чтобы вы ничего не потеряй.

Если это абсолютно необходимо внутри MySQL, вам может быть лучше использовать таблицу HEAP, а не таблицу InnoDB. Вы потеряете свой «дублирующий ключ», но вы всегда можете использовать хранимую процедуру/функцию для обновления. И опять же, у вас всегда может быть запланированный запрос/сценарий по времени для "INSERT INTO... SELECT FROM..." для таблицы типа archive, чтобы ничего не потерять.

Или используйте совершенно другую базу данных для хранения своей статистики. MongoDB имеет upserts и $increments, что делает его очень хорошим выбором для сбора статистики.

person Phillip B Oldham    schedule 08.09.2009
comment
Спасибо! Таблица, с которой это работает, является таблицей памяти. Я обновляю таблицу без памяти каждые 15 минут. - person Nir; 08.09.2009
comment
Тогда я подозреваю, что вы достигли предела того, что может предоставить вам mysql; mysql — отличная небольшая база данных, но она не подходит для всего. Memcached или MongoDB лучше подходят в этом случае. - person Phillip B Oldham; 08.09.2009