|
Вопрос как организовать фишку. PHP + MySQL | ☑ | ||
---|---|---|---|---|
0
Топ 1 программист ми
25.09.13
✎
03:00
|
Всем привет.
У меня есть магазин PHP+MySQL. там есть комменты клиентов. Хочу как на этом форуме(посты) организовать связь постов. То-есть. если человек пишет - (0) то идет ссылка на первый пост. А у первого поста отображается кто на него ссылался. В этом и суть моего вопросы, как лучше реализовать? Предложите ваши варианты, в первую очередь хочется более оптимизировано. Сразу на ум приходит. Человек пишет комментарий, в таблице posts сделать колонку 'to' (тут будет номер поста которому он пишет). А уже при выводе поство, делать левое соединение и смотреть все 'to' кто ссылался на этот пост и писать. но мне кажется так не очень быстро. |
|||
1
Rie
25.09.13
✎
03:10
|
(0) Если речь идёт об SQL и о "быстро" - значит, нужен индекс. А структура данных тут очевидна.
|
|||
2
Топ 1 программист ми
25.09.13
✎
03:15
|
(1) очевидная как я написал в (0) посту?
|
|||
3
kokamoonga
25.09.13
✎
04:30
|
(2) а если в одном комментарии обращение к нескольким?
нужна дополнительная таблица для связи. два поля from, to (pk не считаю). |
|||
4
Топ 1 программист ми
25.09.13
✎
04:47
|
(3) да да тоже подумал про обращение к нескольким.
Видимо один вариант только - внешняя таблица. Но опять же при выводе комментов, каждый коммент будет делать левое соединение =) хотя думаю будет не так долго если на страницу по 20 - 30 комментов. |
|||
5
Rie
25.09.13
✎
04:58
|
(3) Тут как раз нужны два варианта: ответ на пост (и тут возможна только одна ссылка, как и предлагалось в (0)) и ссылка на пост (и тут будут нужны дополнительные ссылки).
Выделение ответа как специального типа ссылки поможет пользователям ориентироваться в разговоре, особенно когда обсуждение идёт активно. |
|||
6
Rie
25.09.13
✎
05:00
|
(4) Скорость обеспечат индексы.
(Не совсем понятно, почему надо именно _левое_ соединение. Как раз внутреннее соединение выделит только те посты, в которых есть ссылки). |
|||
7
kokamoonga
25.09.13
✎
05:06
|
(5) >>> ответ на пост (и тут возможна только одна ссылка
правильно ли я понимаю, что два человека не могут ответить на один комментарий? |
|||
8
Rie
25.09.13
✎
05:08
|
(7) Могут. "Ответные" ссылки лежат в ответах, а не в исходном посте. В (0) как раз из предлагалось поле _to_ - ссылка из комментария на комментируемое.
|
|||
9
Rie
25.09.13
✎
05:10
|
+(8) Но вот ответить одним комментарием сразу на несколько постов - это действительно невозможно. Тут и пригодится вторая таблица "простых" ссылок.
|
|||
10
Rie
25.09.13
✎
05:14
|
+(9) Собственно, это и наблюдается на форумах - два типа организации: в виде "дерева" (например, rsdn) и в виде "потока" (например, mista). Оба способа хороши. А если предусмотреть оба (и дать возможность пользователю переключаться) - так вообще прекрасно получится. IMHO.
|
|||
11
kokamoonga
25.09.13
✎
05:18
|
(8) (9) >>> Но вот ответить одним комментарием сразу на несколько постов - это действительно невозможно. Тут и пригодится вторая таблица "простых" ссылок.
Что значит пригодится? Это вполне стандартный способ связи many-to-many. Поле _to_ совершенно бессмысленно в данном случае. (10) Причем здесь потоки и деревья? Вопрос в том что дополнительная таблица позволяет реализовать оба варианта, тогда как поле _to_ годится только для одного. |
|||
12
Rie
25.09.13
✎
05:21
|
(11) Не бессмысленно. Оно выделяет конкретный пост среди прочих. Не обязательно это делать в виде поля _to_ - но это менее накладно, чем вводить дополнительный признак в табличке "from-to".
|
|||
13
Rie
25.09.13
✎
05:25
|
+(12) Тут ведь две разные задачи - построить дерево и построить набор ссылок. Построить дерево - согласен, это "подзадача" относительно "построить набор ссылок". Но я предлагаю дать пользователю выбор - и если он выбрал дерево, то не тратить силы зря.
(Это как в анекдоте о математиках: "Задача: есть пустой чайник. Надо вскипятить воду. Решение: наливаем в чайник воды, ставим на плиту, кипятим. Следующая задача: есть чайник, в котором налита вода. Надо вскипятить воду. Решение: выливаем воду из чайника и переходим к предыдущей задаче"). |
|||
14
kokamoonga
25.09.13
✎
05:26
|
(12) дублирование данных заложенное в структуре базы данных это всегда накладно. следить за консистентностью какбы надо. или предполагается в _to_ писать ссылку на первый "отвечаемый" пост, а остальное в доп. таблицу?
может я не вкуриваю вашу мысль, но чтобы так как на мисте надо делать через many-to-many. если простая модель один к одному тогда да, можно через это поле. |
|||
15
kokamoonga
25.09.13
✎
05:27
|
(13) дать пользователю выбрать это прекрасная мысль, только как это реализовать если один пост является ответом на несколько, а пользователь выбрал дерево?
|
|||
16
Rie
25.09.13
✎
05:29
|
(14) На _единственный_ отвечаемый пост (иначе это будет уже не дерево).
На Мисте поле _to_ не нужно - тут только "поток". Дублирования данных нет - это ведь разные данные. Есть таблица всех ("произвольных") ссылок. Среди этих ссылок выделяется "главная" (для построения дерева). Как её выделить? Можно вводить булево поле "главная". Можно явно указать. |
|||
17
Rie
25.09.13
✎
05:31
|
(15) Так это как раз выбор пользователя. В дереве нет возможности ответить сразу на несколько постов. Если ему хочется такого - пользователь выбирает "поток".
Удобство дерева в том, что можно выделить и проследить ветку, не заморачиваясь на сторонние комментарии. |
|||
18
Rie
25.09.13
✎
05:33
|
+(17) Конечно, можно рассматривать произвольный орграф и выделять в нём пути. Вопрос в том, насколько это нужно. На мой непросвещённый взгляд, такая потребность если и возникает - то крайне редко (у меня, по крайней мере, пользователи такого ни разу не требовали).
|
|||
19
kokamoonga
25.09.13
✎
05:33
|
(16) ерунду вы пишете. разнородный подход к однородным данным, пишем однородные данные в разные таблицы...
(17) это проблема не структуры хранения, а конкретных реализаций фронтендов. ничто не мешает показывать пользователю конкретные треды основываясь на том же самом many-to-many |
|||
20
Rie
25.09.13
✎
05:37
|
(19) Да ни хрена они не однородные. Это как раз разные структуры. И дело тут не в количестве таблиц - можно и в одной хранить. Дело как раз в том, что для дерева нужна дополнительная информация. Чтобы получилось именно дерево.
Насчёт "конкретных реализаций фронт-эндов" - тут не согласен, поскольку считаю, что структура данных - первична. Но согласен с тем, что моё мнение в данном случае - следствие моих пристрастий. И другое мнение - ничем не хуже моего. |
|||
21
Rie
25.09.13
✎
05:39
|
+(20) Вы исходите из many-to-many. Но дерево - это НЕ many-to-many, это - many-to-1 (и это - принципиальная его особенность). Вот отсюда и возникает разница между моим и Вашим способами.
|
|||
22
kokamoonga
25.09.13
✎
05:46
|
(20) данные однородны. это информация об отвеченных постах записанная в разные таблицы.
так что же все-таки мешает строить дерево по дополнительной таблице from,to ? (21) many-to-many очень легко превращается в many-to-one ( вам ведь не нужно объяснять как? ), о чем я собственно и говорю. а вот предлагаемая вами структура умеет только то что умеет. я понимаю что такое дерево. дело в том, что в many-to-many таблице содержиться множество деревьев, в том числе может быть несколько деревьев содержащих один комментарий в поле from. улавливаете мысль? показать все эти деревья ( или лучше более привычное "нити" ) это проблема конкретной реализации фронтенда, а вовсе не структуры хранения. |
|||
23
Rie
25.09.13
✎
05:50
|
(22) Вашу мысль я прекрасно понимаю (си. (18)).
Но моя мысль несколько в ином: есть две принципиально (с точки зрения _пользователя_) разных задачи. Пользователь может вести с кем-то диалог - и для него тут важно, кто кому ответил. При этом в текстах могут быть ссылки на сторонние посты. И при этом может НЕ быть ссылки на "отвечаемый" пост (но информация, кто кому отвечал - значима). Пользователю может быть по барабану, кто кому отвечал. Форум. Все отвечают всем. Важны только ссылки. Вот поэтому я и предлагаю для двух задач - два механизма. Они ортогональны. Каждый решает свою задачу _независимо_ от другого. |
|||
24
kokamoonga
25.09.13
✎
05:55
|
(23) да понял про сторонние ссылки. ну тут уж без доп. таблицы не обойтись.
при прочих равных я бы выбрал все же две таблицы m2m. на производительности это начнет сказываться при очень внушительных размерах таблиц, а механизм получается более гибким. |
|||
25
Rie
25.09.13
✎
05:57
|
(24) Согласен, что в общем случае тут две таблицы m2m. Просто на практике мне не встречалось, чтобы требовалось именно 2m во второй таблице, все хотят максимум дерево.
|
|||
26
kokamoonga
25.09.13
✎
05:59
|
(25) ТС хочет "как на этом форуме(посты) организовать связь постов". Оттуда и пляшем.
|
|||
27
Rie
25.09.13
✎
06:00
|
(26) "Желание заказчика - закон" :-)
В таком случае - сдаюсь. Решение - в (3). |
|||
28
Топ 1 программист ми
25.09.13
✎
06:21
|
Ну вот я думаю какой вариант выбрать.
1) в самих комментах добавить 'to' или даже 'touser' в итоге коммент будет предназначен ТОЛЬКО для другого коммента, или юзера. Плюсы: - быстрая работа, нет внешних соединений - удобно потом выводить автарам комментов кто им отвечал. Минусы: - в одном комменте не получится сразу ответить на два других 2) второй вариант, сделать отдельную таблицу (fromid, toid с индексами). Плюсы: - можно хоть сколько ссылок на комменты из одного коммента Минусы: - лишняя таблица - лишние записи, если на один коммент будут ссылаться другие 20 комментов = 20 записей - лишние соединения. При получение самого коммента, придется делать соединение к новой таблице (fromid, toid) и получать все ссылки .... хз что выбрать, первый вариант удобный и очень быстрый. второй вариант грамоздкий, лишние запросы. не забывайте что ещё идут соединения для получения данных об авторе коммента и т.д. |
|||
29
Топ 1 программист ми
25.09.13
✎
06:26
|
Со вторым вариантом из (28) получится такой вид запроса.
Условие: есть пост(коммент) на него ссылаются другие 4 коммента. таблица: комменты Ид, автор, текст ------------------> таблица:ссылки (фром, ту) ------------------> по ту = комменты.ид ------------------> выбрать фром результат: -----------------------> ид, автор, текст, фром1 -----------------------> ид, автор, текст, фром2 -----------------------> ид, автор, текст, фром3 -----------------------> ид, автор, текст, фром4 В итоге вместо одной строки, он вернет четыре! разбив по ИД ссылающего |
|||
30
Топ 1 программист ми
25.09.13
✎
06:27
|
Итог:
если на странице 30 комментов. и у каждого коммента будет по 4 ссылки на друг друга. 30 * 4 = 120 записей из базы |
|||
31
Rie
25.09.13
✎
06:27
|
(28) Это зависит только от тебя. Есть две _разные_ задачи. С _разными_ решениями. Надеюсь, что наше с kokamoonga обсуждение (а он - _очень_ грамотный в этих вопросах человек) поможет в выборе (хотя я бы предложил реализовать _оба_ варианта).
|
|||
32
Rie
25.09.13
✎
06:29
|
(29) А вот тут - не понял. Тебе нужны номера постов? Ну так их и будет 4. Или только авторы? Тогда зачем тебе спрашивать номера постов.
|
|||
33
Rie
25.09.13
✎
06:30
|
(30) 120 записей... Жуткая цифра... Не, ну в 1980-х это, наверное, имело значение (хотя опыт FIDO как бы намекает - не имело).
|
|||
34
Топ 1 программист ми
25.09.13
✎
06:33
|
(32) ну в смысле если без темы ссылок то будет результат
ид, автор, текст и так каждый коммент. Если со ссылками и на этот пост есть 4 ссылки, будет такой результат ид, автор, текст, фромИд1 ид, автор, текст, фромИд1 ид, автор, текст, фромИд1 ид, автор, текст, фромИд1 он же будет повторять левый запрос каждый раз. Это только 1 пост из 30. (33) может мне не заморачиватся а просто делать соединение и получать все ссылки |
|||
35
kokamoonga
25.09.13
✎
06:33
|
(30) даже если их будет 120 тысяч это не отразится сколько-нибудь заметно на конечном результате даже при наличии двух LEFT JOIN
|
|||
36
Топ 1 программист ми
25.09.13
✎
06:34
|
(35) ну запрос же будет дольше? страница грузится будет дольше?
|
|||
37
Rie
25.09.13
✎
06:35
|
(36) Нет. (Хотя если у тебя сервер стоит на калькуляторе - тогда да).
|
|||
38
kokamoonga
25.09.13
✎
06:35
|
(36) чтобы скорость выполнения запроса стала узким местом нужно чтобы таблицы были очень внушительных размеров. 300-500 тысяч записей. Я полагаю вам это не грозит в ближайшее время
|
|||
39
Rie
25.09.13
✎
06:36
|
(Вот я не понимаю, а почему JOIN - LEFT? Чтобы SQL сервер запутать, и он не смог этот запрос оптимизировать?)
|
|||
40
Топ 1 программист ми
25.09.13
✎
06:37
|
(37) и (38) спс за ответы =) я думаю тут уже все понятно.
начну со второго варианта(с доп. таблицей ForTo) если будет плохо работать сделаю просто + колонку To (39) посоветуй как лучше |
|||
41
kokamoonga
25.09.13
✎
06:39
|
(39) нужно смотреть изначально предполагаемые нагрузки. INNER при достаточном размере таблицы может запросто инстанс сервера положить. Хотя может это и предрассудки... 5.x давно на дворе...
|
|||
42
Rie
25.09.13
✎
06:39
|
(40) Не могу посоветовать, поскольку текста запроса не вижу.
Но что-то мне подсказыват, что рядом с LEFT JOIN стоит та или иная проверка на NULL... |
|||
43
Rie
25.09.13
✎
06:41
|
(41) (а) Каком размере таблицы? (б) в 5.5 и выше вроде как таких проблем нет.
(То есть, перестраховаться, конечно, оно всегда полезно. Вот только предполагаю, что в данной задаче не от этого надо страховаться :-) |
|||
44
Rie
25.09.13
✎
06:43
|
+(43) Впрочем, тут Вы, насколько я знаю, компетентнее меня. Поэтому рекомендую ТС слушать всё же Вас.
|
|||
45
kokamoonga
25.09.13
✎
06:56
|
(43) (44)
a) ну точных размеров я не назову. Я все же не MySQL-гуру. b) на 5.1. INNER JOIN двух таблиц ~50к и ~30к записей проходит нормально:) Очевидно размеры недостаточны. Правда мускулу выделено 1024М памяти. Может это я просто ношусь со старыми страшилками. В данном случае страховаться от иннер джойнов несколько преждевременно:) |
|||
46
Rie
25.09.13
✎
07:01
|
(45) Ну, лучше перебдеть, чем недобдеть :-)
|
|||
47
Топ 1 программист ми
25.09.13
✎
07:29
|
Ещё вопрос.
Есть таблица комментов: ид, товар, автор, текст если делать ещё одну таблицу Ссылки: ОткудаИд, КудаИд то туда я убду писать ИД самих комментов верно? Но как быть, на самой странцие товара комменты идут под нумерацией с 1... (как на форуме). тогда как переводить ИД комментов в номера. Как я узнаю что в таблице "ссылки" коммент источник под номером 9899 является 5 комментов в теме? |
|||
48
Топ 1 программист ми
25.09.13
✎
07:30
|
или тут на форуме сделали так, что в таблице посты хранится не только глобальный ИД поста, но и локальный относительно темы?
|
|||
49
Rie
25.09.13
✎
08:52
|
(48) Посмотри внимательно на ссылку, когда жмакаешь по (номер) на этом форуме.
|
|||
50
kokamoonga
25.09.13
✎
15:54
|
(44) (46) поковырял для интереса INNER и LEFT в профайлере. Существенной разницы не заметил. Видимо это у меня все же старые фобии, не имеющие отношения к реальности:)
|
|||
51
Asmody
25.09.13
✎
15:59
|
На мисте никаких дополнительных таблиц нет. Номера ответов парсятся при выводе
|
|||
52
Asmody
25.09.13
✎
16:01
|
(48) в таблице есть id сообщения, глобальный, topic_id — id темы и n — номер сообщения в теме
|
|||
53
Asmody
25.09.13
✎
16:02
|
(41) мисту не кладет, а у нас размер таблиц хороший. Правда у нас percona стоит сейчас.
|
|||
54
kokamoonga
25.09.13
✎
16:17
|
(53) да я уже признал, что боюсь бабушкиных страшилок:)
Разве между percona и оракловским движком есть существенная разница в производительности? |
|||
55
Asmody
25.09.13
✎
16:43
|
(54) Percona как раз форк, нацеленый на performance. Там ребята изначально занимались профессиональными тюнингом MySQL, потом форкнули и серьезно допилили. http://www.percona.com/software/percona-server
Настолько серьезно, что движок XtraDB теперь включен в MariaDB как один из основных. |
|||
56
kokamoonga
25.09.13
✎
16:48
|
(55) я в курсе про форк. Даже немного пробовал Maria на небольшоим некоммерческом сайтике.
Но оценить производительность там конечно никак, так баловство. А миста вполне себе показательный тестовый стенд, есть где развернуться. |
|||
57
Jump
25.09.13
✎
17:24
|
(0)Сделай ровно наоборот, сделай колонку "ссылки" и дописывай в нее при записи поста который ссылается его номер.
|
|||
58
Топ 1 программист ми
26.09.13
✎
01:34
|
(52) а можно подробнее?
Понятно когда выводится пост, идет парсинг и заменяется "(1)" на ссылку. Номер страницы идет расчет (кол на страницу / указанный номер поста). А как вычисляется КТО ссылался на пост? не куда, а кто? |
|||
59
Asmody
26.09.13
✎
01:51
|
(58) отдельным проходом анализируются все сообщения, собираются в массив, где ключи - сообщения на которые ссылаются, а значения - массивы сообщений, из которых ссылаются. потом это выводится справа от сообщения
|
|||
60
Rie
26.09.13
✎
03:20
|
(59) А в чём преимущество такого анализа перед хранением ссылок в таблицах?
|
|||
61
Web00001
26.09.13
✎
04:29
|
(60) Видимо в отсутствии дополнительной таблицы, дополнительных движений по чтению\записи этой таблицы. Но я думаю здесь главный момент простота реализации, при абсолютно тех же если не меньших накладных расходах.
|
|||
62
Rie
26.09.13
✎
04:33
|
(61) Мне кажется, что вариант с дополнительной таблицей - как раз удобнее. Один раз, при поступлении очередного поста, обрабатываем - а дальше всё уже готовенькое. Заодно избавляемся от ссылок на несуществующие посты (на "Мисте" такое регулярно встречается).
|
|||
63
Web00001
26.09.13
✎
04:43
|
Может быть, все зависит от того как работает на данные момент текущее решение. Мне не понятно зачем дублировать данные. Я обычно стараюсь избегать этого.
|
|||
64
Rie
26.09.13
✎
05:03
|
(63) Я так понял, что у ТС текущего решения попросту нет, он только начинает его ваять.
Насчёт дублирования данных - оно может оказаться полезным как раз для ускорения вычислений. Но тут (в таблицах перекрестных ссылок на посты) нет дублирования данных. |
Форум | Правила | Описание | Объявления | Секции | Поиск | Книга знаний | Вики-миста |