Модераторы: skyboy

Поиск:

Ответ в темуСоздание новой темы Создание опроса
> [PostgreSQL]Подсчет количества сообщений в теме, Как сделать более оптимальным... 
:(
    Опции темы
Dima 2015
Дата 28.8.2008, 11:23 (ссылка) | (нет голосов) Загрузка ... Загрузка ... Быстрая цитата Цитата


Опытный
**


Профиль
Группа: Участник
Сообщений: 287
Регистрация: 16.3.2008
Где: SPb

Репутация: нет
Всего: 2



Доброго времени суток коллеги.

Хочу с вами посоветоваться вот по какому вопросу. Допустим такая ситуация - есть стандартный форум аля темы - сообщения.

Темы:

Код

CREATE table "forum_topic" (
  "id"            serial  PRIMARY KEY,
  "title"      varchar NOT NULL,
  "author"      integer NOT NULL REFERENCES "user",
  "last_modified"      timestamp NOT NULL,
  "last_user"      integer NOT NULL REFERENCES "user"
);


Сообщения:

Код

CREATE table "forum_post" (
  "id"            serial  PRIMARY KEY,
  "forum_topic"   integer NOT NULL REFERENCES "forum_topic",
  "author"      integer NOT NULL REFERENCES "user",
  "date"      timestamp NOT NULL,
  "message"      varchar NOT NULL
  
);


И вот я хочу вывести список тем с указанием всяческой информации о нем, в том числе количества сообщений в нем. Я конечно могу поступить просто, сделав вложенный запрос аля

Код

SELECT
    forum_topic.id,
    forum_topic.group,
    forum_topic.title,
    forum_topic.author AS author_id,
    "user".name AS author_name,
    forum_topic.last_modified,
    forum_topic.last_user AS last_user_id,
    (SELECT name FROM "user" WHERE "user".id = forum_topic.last_user) AS last_user_name,

-- и вот тут считаем число постов в теме:
    (SELECT COUNT(*) FROM forum_post WHERE forum_post.forum_topic = forum_topic.id) AS posts_quantity
 
FROM forum_topic
LEFT JOIN "user" ON "user".id = forum_topic.author


Однако, такая конструкция начинает прилично тормозить когда тем и постов в них много. А не дай бог я захочу еще по этому количеству постов отсортировать, тогда база будет сначала считать кол-во постов для ВСЕХ тем и лишь потом делать сортировку, выливается это в запросы длящиеся по 40 секунд уже при 1000 тем и сообщений.

Поэтому приходит в голову мысль держать число постов в теме непосредственно в таблице forum_topic. И вроде как это спасает, но возникает новая проблема...

Такой подход означает, что при КАЖДОМ добавлении и удалении поста мне нужно делать пересчет количества постов и обновлять соотв. колонку в таблице тем  forum_topic. У меня конечно есть ф-ция, удаляющая пост и я могу ее дополнить - вписать в нее пересчет, аналогично для добавления.

Вот хочется спросить - можно ли решить эту задачу более оптимально?

Я слышал про такую вещь как Триггеры в SQL и триггерные ф-ции. Что мол можно повесить прямо SQL-ную ф-цию пересчета постов, которая будет запускаться как только будет дана команда DELETE / INSERT для таблицы постов forum_post. Правда тут еще не очень понятно как группу передавать, для которой этот пересчет надо делать, ну это уже надо разбираться с этими триггерами... вот собрался, но все же хотел спросить может чего поумнее придумать можно?
PM MAIL ICQ   Вверх
HackMan
Дата 28.8.2008, 11:36 (ссылка) | (нет голосов) Загрузка ... Загрузка ... Быстрая цитата Цитата


Юзверь-программист
**


Профиль
Группа: Участник
Сообщений: 391
Регистрация: 18.6.2005
Где: .ua

Репутация: нет
Всего: 9



Триггеры появились в MySQL начиная с 5ой версии. Почитать про них можно здесь или здесь. Они увеличивают производительность за счёт уменьшение информации, которое пересылается от PHP к MySQL.

Это сообщение отредактировал(а) HackMan - 28.8.2008, 11:40


--------------------

Завтра - это самый загруженный день недели smile

user posted image

user posted image
PM MAIL ICQ   Вверх
Dima 2015
Дата 28.8.2008, 11:38 (ссылка) | (нет голосов) Загрузка ... Загрузка ... Быстрая цитата Цитата


Опытный
**


Профиль
Группа: Участник
Сообщений: 287
Регистрация: 16.3.2008
Где: SPb

Репутация: нет
Всего: 2



HackMan, пасибо. Правда у меня PostgreSQL, ну да не думаю что шибко большая разница...

Так что, верная мысль что именно так нужно данную проблему решать?

Это сообщение отредактировал(а) Dima 2015 - 28.8.2008, 11:40
PM MAIL ICQ   Вверх
HackMan
Дата 28.8.2008, 11:42 (ссылка) | (нет голосов) Загрузка ... Загрузка ... Быстрая цитата Цитата


Юзверь-программист
**


Профиль
Группа: Участник
Сообщений: 391
Регистрация: 18.6.2005
Где: .ua

Репутация: нет
Всего: 9



Я не думаю что использование триггеров сильно увеличит производительность, но мне самому интересно почитать мнение шарящих в этом деле  smile Предложенный тобой второй вариант (с дополнительным полем) давно проверен временем и с успехом используется в крупных CMS и на крупных серверах.

Это сообщение отредактировал(а) HackMan - 28.8.2008, 11:43


--------------------

Завтра - это самый загруженный день недели smile

user posted image

user posted image
PM MAIL ICQ   Вверх
Dima 2015
Дата 28.8.2008, 11:48 (ссылка) | (нет голосов) Загрузка ... Загрузка ... Быстрая цитата Цитата


Опытный
**


Профиль
Группа: Участник
Сообщений: 287
Регистрация: 16.3.2008
Где: SPb

Репутация: нет
Всего: 2



HackMan, понимаешь какая штука. Тут вопрос даже не в производительности а в общем подходе к проектированию проекта.

Вот представим, что у меня удаление и добавление постов происходит в 10ти разных местах кода, и далеко не всегда используется 1 и та же ф-ция. Ну вот допустим... Скажем у админа может быть опция "удалить все отмеченные сообщения", это будет работать уже другая ф-ция, и к ней тоже надо будет приписать пересчет постов.

А потом я еще захочу добавить какую-то ф-цию удаления или добавления постов, и когда-нибудь я обязательно забуду дописать ф-цию пересчета в нужное место. А потом буду искать где же.. где же...

Поэтому меня интересует как в принципе к таким вещам правильно подходить, это могут быть вовсе и не темы-посты, а скажем группы-участики, а там уж мест где может измениться число участников до дури.
PM MAIL ICQ   Вверх
HackMan
Дата 28.8.2008, 12:10 (ссылка) | (нет голосов) Загрузка ... Загрузка ... Быстрая цитата Цитата


Юзверь-программист
**


Профиль
Группа: Участник
Сообщений: 391
Регистрация: 18.6.2005
Где: .ua

Репутация: нет
Всего: 9



В этом плане триггеры - очень удобная вещь. Думаю, тебе будет интересен этот примерчик.


--------------------

Завтра - это самый загруженный день недели smile

user posted image

user posted image
PM MAIL ICQ   Вверх
Dima 2015
Дата 28.8.2008, 12:12 (ссылка) | (нет голосов) Загрузка ... Загрузка ... Быстрая цитата Цитата


Опытный
**


Профиль
Группа: Участник
Сообщений: 287
Регистрация: 16.3.2008
Где: SPb

Репутация: нет
Всего: 2



HackMan, ага, нашел его по поиску еще до того как эту тему создал, но все равно спасибо ))))
PM MAIL ICQ   Вверх
bobik02
Дата 28.8.2008, 12:19 (ссылка) | (нет голосов) Загрузка ... Загрузка ... Быстрая цитата Цитата


Опытный
**


Профиль
Группа: Участник
Сообщений: 451
Регистрация: 26.11.2007

Репутация: нет
Всего: 14



Логически получается, что триггер  удобный и в плане производительности и в проектировании.  smile 

Dima 2015, Если напишете триггер, то желательно закопипастить его сюда.  smile 
(самому интересно, думаю и другим тоже будет интересно)


--------------------
Have a nice day
PM   Вверх
Dima 2015
Дата 28.8.2008, 12:21 (ссылка) | (нет голосов) Загрузка ... Загрузка ... Быстрая цитата Цитата


Опытный
**


Профиль
Группа: Участник
Сообщений: 287
Регистрация: 16.3.2008
Где: SPb

Репутация: нет
Всего: 2



bobik02, не вопрос. Вот ща у меня штук 10 вкладок с ФАКами по триггерам открыты, ща прочитаю, напишу.. получете, а пока ждем авторитетов, которые скажут что все нетак и не эдак smile
PM MAIL ICQ   Вверх
skyboy
Дата 28.8.2008, 12:55 (ссылка) | (нет голосов) Загрузка ... Загрузка ... Быстрая цитата Цитата


неОпытный
****


Профиль
Группа: Модератор
Сообщений: 9820
Регистрация: 18.5.2006
Где: Днепропетровск

Репутация: 15
Всего: 260



категорически не понимаю.
почему вместо join'a и группировки выполняется подзапрос?
почему делается left, а не inner join на таблицу user? неужели могут быть темы без автора?
зачем триггеры там, где можно оптимизировать запрос? кроме того, при постраничном выводе, можно сразу отсортировать записи и выбрать необходимое количество, вместо подсчета количества сообщений для всех тем...
PM MAIL   Вверх
Dima 2015
Дата 28.8.2008, 13:16 (ссылка) | (нет голосов) Загрузка ... Загрузка ... Быстрая цитата Цитата


Опытный
**


Профиль
Группа: Участник
Сообщений: 287
Регистрация: 16.3.2008
Где: SPb

Репутация: нет
Всего: 2



Цитата

почему вместо join'a и группировки выполняется подзапрос?



skyboy, вот в этом месте по-подробней можно плиз?

Касаемо left / inner - когда писал, еще не вполне понимал что пишу, скопировал со старых баз. Нет не может быть тем без автора, да и бох с ними.

Цитата

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


Так вопрос в теме так и звучит - как сделать по-другому? Вот надо мне отсортировать темы по количеству сообщений, если в таблице нет специальной для этой колонки и вложенного селекта я не делаю, то как?
PM MAIL ICQ   Вверх
skyboy
Дата 28.8.2008, 13:48 (ссылка) | (нет голосов) Загрузка ... Загрузка ... Быстрая цитата Цитата


неОпытный
****


Профиль
Группа: Модератор
Сообщений: 9820
Регистрация: 18.5.2006
Где: Днепропетровск

Репутация: 15
Всего: 260



Цитата(Dima 2015 @  28.8.2008,  12:16 Найти цитируемый пост)
Вот надо мне отсортировать темы по количеству сообщений

во-первых, в первом сообщении на сортировку намека нет.
во-вторых, зачем делать сортировку по количеству сообщений?
Цитата(Dima 2015 @  28.8.2008,  12:16 Найти цитируемый пост)
skyboy, вот в этом месте по-подробней можно плиз?

postgresql: join
postgresql: секция GROUP BY
PM MAIL   Вверх
Dima 2015
Дата 28.8.2008, 13:52 (ссылка) | (нет голосов) Загрузка ... Загрузка ... Быстрая цитата Цитата


Опытный
**


Профиль
Группа: Участник
Сообщений: 287
Регистрация: 16.3.2008
Где: SPb

Репутация: нет
Всего: 2



skyboy, намек есть.

"А не дай бог я захочу еще по этому количеству постов отсортировать, тогда база будет сначала считать кол-во постов для ВСЕХ тем и лишь потом делать сортировку".

Я уже понял что нужно GROUP BY курить : ))) Курю... хотя все равно был бы признателен если бы явно показал кто как число постов заджойнить.
PM MAIL ICQ   Вверх
Dima 2015
Дата 28.8.2008, 14:09 (ссылка) | (нет голосов) Загрузка ... Загрузка ... Быстрая цитата Цитата


Опытный
**


Профиль
Группа: Участник
Сообщений: 287
Регистрация: 16.3.2008
Где: SPb

Репутация: нет
Всего: 2



Вроде понял... чтото в этом духе:

Код

SELECT    forum_topic.id,
    forum_topic.title,
    COUNT(forum_post.id) AS post_quantity
FROM forum_topic
LEFT JOIN forum_post ON forum_post.forum_topic = forum_topic.id

GROUP BY forum_topic.id, forum_topic.title
ORDER BY post_quantity DESC


Работает вроде... и что, меня это полностью спасет от вышеизложенных проблем?
PM MAIL ICQ   Вверх
Dima 2015
Дата 28.8.2008, 14:27 (ссылка) | (нет голосов) Загрузка ... Загрузка ... Быстрая цитата Цитата


Опытный
**


Профиль
Группа: Участник
Сообщений: 287
Регистрация: 16.3.2008
Где: SPb

Репутация: нет
Всего: 2



Хех... все хорошо в вышеописанном способе, но вот не задача. А если мне нужно еще посчитать что-нибудь из той же таблицы? Ну например тоже число постов этого же топика, но у которых автор - я. И как тогда? Ведь 2 раза ДЖОЙН сделать нельзя, а куда приклеить условие?
PM MAIL ICQ   Вверх
Страницы: (3) Все [1] 2 3 
Ответ в темуСоздание новой темы Создание опроса
0 Пользователей читают эту тему (0 Гостей и 0 Скрытых Пользователей)
0 Пользователей:
« Предыдущая тема | Составление SQL-запросов | Следующая тема »


 




[ Время генерации скрипта: 0.1971 ]   [ Использовано запросов: 22 ]   [ GZIP включён ]


Реклама на сайте     Информационное спонсорство

 
По вопросам размещения рекламы пишите на vladimir(sobaka)vingrad.ru
Отказ от ответственности     Powered by Invision Power Board(R) 1.3 © 2003  IPS, Inc.