Имя: Пароль:
IT
Веб-мастеринг
Вопрос как организовать фишку. 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) Я так понял, что у ТС текущего решения попросту нет, он только начинает его ваять.
Насчёт дублирования данных - оно может оказаться полезным как раз для ускорения вычислений.
Но тут (в таблицах перекрестных ссылок на посты) нет дублирования данных.