[ Поиск ] - [ Пользователи ] - [ Календарь ]
Полная Версия: Оптимизировать сбор статистики из SQL
NitroGenerate
Всем привет. Решил написать страничку с отчетом пользователя. После первого написания время генерации составило 30 секунд. Я схватился за голову.
Начну из далека. Создал в базе таблицу с названием user_log, в которую записываются все действия пользователей, которые имеют права выше обычного юзера.
И так у меня сейчас около 15 модераторов.
Каждый раз при редактировании, удалении или добавлении новости. Действие записывается в лог. В котором есть (номер пользователя, номер новости, и комментарий в виде "Пользователь удалил объявления из базы", или отредактировал, или добавил. И последняя графа время.
Я создал функцию, которая подсчитывает все объявления где комментарий равен "Пользователь удалил объявления из базы"
Принцип
$count=mysql_result(mysql_query("SELECT count(*) from ...where comment='Пользователь удалил объявления из базы' and time>".$time." and time<".$time2.""));

И так у меня таблица из 15 пользователей и 5ти дней, сегодня, вчера, позавчера, поза-позавчера и поза-поза-позавчера.
В результате имеем
Время генерации: 19,4374 Запросов в бд: 394.
Но я собираюсь идти дальше, мне нужен отчет за месяц, по дням. И в дне где пользователь добавил с 0 до 8ми утра с 9ми до 18 и с 18 до 24.
Где отредактировал
где удалил,
где добавил в архив.
посчитаем...
30 дней*4 (что сделал)*3(ночь, рабочее врем, вечер)=360 запросов. В лучшем случае, в худшем я что-нибудь придумаю еще и их будет 700.
Как быть мне, как считать ?
Может быть вытащить из базы весь месяц, перебрать его циклом, и в цикле же разложить по переменным, а дальше просто их опубликовать.?
Или может так долго выполняется подсчет, из за того, что я обращают к длинному тексту, может на добавить новость назначить число служебное, скажем 1, на удалить 2 и тд ?
Я в замешательстве



Спустя 25 минут, 24 секунды (24.02.2012 - 16:23) Nikitian написал(а):
group by to_days(`time`)
Выведет по дням статистику. where comment="" - заменить на какое-нибудь числовое поле с идентификатором действия и индексом по этому полю.

Спустя 11 минут, 38 секунд (24.02.2012 - 16:35) NitroGenerate написал(а):
Число, на много повысит производительность?

С этим немного не понял,
group by to_days(`time`),
у меня время в юниксе записывается,
И не понимаю, как сгруппировать допустим целый месяц
С 9ти утра и до 6ти вечера.

Спустя 9 минут, 59 секунд (24.02.2012 - 16:45) Nikitian написал(а):
Число повысит. Намного или нет, зависит от типа поля comment, данных, которые в этом поле содержатся, и индексов.
Если time в юниксе, то так: group by to_days(date_format(`time`,'%Y-%m-%d'))
Про группировку месяца с определёнными промежутками времени - это извращение сложно представить как оптимизировать, не меняя структуру таблицы и способа записи. Так же неясно какие вообще группировки могут потребоваться. Если полностью различные группировки, то тут только ваше решение в лоб, с возможностью асинхронного подсчёта результата.

Спустя 2 дня, 17 часов, 28 минут, 22 секунды (27.02.2012 - 10:13) NitroGenerate написал(а):
Хорошо, тогда другой вопрос, что быстрее:
Вытащить из бд все действия пользователя за месяц и потом в цикле разложить на 4 полки.
Или выполнить 4 count запроса в бд и загнать их в 4 переменные?

Спустя 6 минут, 17 секунд (27.02.2012 - 10:19) Visman написал(а):
NitroGenerate, а индексы в таблице по полям используемым в условии созданы?
Цитата
После первого написания время генерации составило 30 секунд.

Из-за этого наверное.

Спустя 55 минут, 4 секунды (27.02.2012 - 11:15) Placido написал(а):
Как уже говорили, индексы стоят? Составной индекс на поля comment + data поставили?
ALTER TABLE ... ADD INDEX (`comment`,`time`)

Спустя 1 час, 29 минут, 25 секунд (27.02.2012 - 12:44) NitroGenerate написал(а):
Кхе, спасибо, про индексы что-то вообще не думал. Создал. Быстрее стало в 5 раз. Но, все равно, долго...

Спустя 4 минуты, 3 секунды (27.02.2012 - 12:48) vagrand написал(а):
1. Замена текстового поля на int с типом действия на много сократит как сам размер таблицы (не говоря уже про размер для индексов), так и время для выборки;
2. Если есть необходимость в группировках, то я бы порекомендовал сделать отдельные таблицы, куда уже при записи в users_log подсчитывать данные в нужном тебе формате при помощи триггеров. Таким образом при выборе тебе просто нужно будет сделать легкий select с условием по датам и без каких-либо группировок.

Спустя 8 минут, 46 секунд (27.02.2012 - 12:57) Visman написал(а):
1. Я бы предложил вместо текстового поля comment сделать числовое с конечным набором кодов по действиям.
2. Хранить год, месяц, день в отдельных полях как числа.
3. Для периодов в сутках по которым нужно получать обобщенную статистику завести отдельное поле с кодами, пример с 0 до 8ми утра - код 0, с 9ми до 18 - код 1, с 18 до 24 - код 2.

Запрос же делать один
SELECT COUNT(*) AS KOLVO, DEYSTVIE, GOD, MESYC, DEN, KODVREMY FROM ... WHERE GOD=2012 AND MESYC=2 AND ... GROUP BY GOD, MESYC, DEN, KODVREMY, DEYSTVIE

А дальше массив в цикле выводишь в виде статистики

Спустя 11 минут, 4 секунды (27.02.2012 - 13:08) vagrand написал(а):
SELECT COUNT(*) AS KOLVO, DEYSTVIE, GOD, MESYC, DEN, KODVREMY FROM ... WHERE GOD=2012 AND MESYC=2 AND ... GROUP BY GOD, MESYC, DEN, KODVREMY, DEYSTVIE


Но от group by то вы не уходите при таком методе, а ведь он и есть основное зло после текстового поля.
Быстрый ответ:

 Графические смайлики |  Показывать подпись
Здесь расположена полная версия этой страницы.
Invision Power Board © 2001-2024 Invision Power Services, Inc.