Jump to content
  • 0

Структура таблиц


crautcher
 Share

Question

спросил сперва на другом форуме , там мне ниче так никто и не ответил :

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

Link to comment
Share on other sites

Recommended Posts

  • 0

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

А в текущей задаче вроде как каждое из слов может иметь множество ссылок на другие слова. Или я чего-то не понимаю?

PS: то есть я вижу одну таблицу со всеми словами, решение -- вторичный ключ указывающий на первое из группы синонимов, так? А в логике программы определять всю группу, слова, которые ссылаются на "первый" синоним.

PPS: т.е. как-то так вижу

CREATE TABLE `words` (
`id` INT(10) UNSIGNED NULL AUTO_INCREMENT,
`word` VARCHAR(255) NULL,
`parent_synonym_id` INT UNSIGNED NULL,
PRIMARY KEY (`id`),
UNIQUE INDEX `word` (`word`),
INDEX `parent_synonym_id` (`parent_synonym_id`)
)

Link to comment
Share on other sites

  • 0

Значить, стандартное один ко-многим, но только внешне.

CREATE TABLE words
(
id integer NOT NULL,
word text,
CONSTRAINT words_pkey PRIMARY KEY (id )
)

CREATE TABLE word_syn
(
word_id integer NOT NULL,
syn_id integer NOT NULL,
CONSTRAINT world_syn_pkey PRIMARY KEY (word_id , syn_id ),
CONSTRAINT world_syn_syn_id_fkey FOREIGN KEY (syn_id)
REFERENCES words (id) MATCH SIMPLE
ON UPDATE CASCADE ON DELETE CASCADE,
)

word_id тут или счетчик группы синонимов, а лучше, что бы не путаться - id первого слова группы

В таблице прописываем эти группы синонимов.

words:
1;"синоним А 1"
2;"синоним Б 1"
3;"синоним А 2"
4;"синоним А 3"
5;"синоним Б 2"

word_syn:
1;1
1;3
1;4
2;2
2;5

Ну и запрос

SELECT 
syn.word
FROM
public.words src
INNER JOIN
public.word_syn link
ON (src.id = link.syn_id)
INNER JOIN
public.word_syn link2
ON (link.word_id = link2.word_id)
INNER JOIN
public.words syn
ON (link2.syn_id = syn.id)
WHERE
src.word = 'синоним А 1';

Edited by MiksIr
Link to comment
Share on other sites

  • 0

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

Link to comment
Share on other sites

  • 0

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

Только так и надо решать. Можно сразу хранить json-объект (вернее его текстовое представление)

Тогда запрос будет простым и быстрым.

Link to comment
Share on other sites

  • 0

Слово     | Группа
-------------------
пить | 1
бухать | 1
колдырять | 1
квасить | 1
курить | 2
смолить | 2
дымить | 2
пыхать | 2
-------------------

Ищем слово -> Определяем группу синонимов -> берём все слова из группы синонимов

Или я не прав, и есть более простые решения ?

Link to comment
Share on other sites

  • 0

Это будет говнокод.

Да конечно! Во всем мире это используется в высоконагруженных системах, а у него это говнокод.

:rofl:

Или я не прав, и есть более простые решения ?

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

Link to comment
Share on other sites

  • 0

Давай ты еще раскажешь про высоконагруженные проекты во всем мире, ага.

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

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

Эта структура может быть использована для хранения нормализованных данных, но не для вывода. Потому что там JOIN надо применять.

JOIN можно и нужно применять, когда нужно. Если вы думаете, что разбив джойн на два запроса вы всегда получите адский профит, вы безумно ошибаетесь.

Edited by MiksIr
Link to comment
Share on other sites

  • 0

Высоконагруженные проекты не работают с денормализованными данными, они их создают из нормализованных в виде кеша.

Проводя денормализацию. В кеше и хранятся денормализованные данные. А кэш иногда проще вообще не использовать, так как затраты на обновление кеша могут привысить затраты на обработку запроса базой.

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

В чем проблема? Вам нужно всего лишь обновить n строк, где n - количество синонимов в группе. Это предсказуемое количество.

JOIN можно и нужно применять, когда нужно. Если вы думаете, что разбив джойн на два запроса вы всегда получите адский профит, вы безумно ошибаетесь.

Только весь прикол в том, что один запрос оффлайновый, а второй - онлайновый. И да, я получу адский профит на всех этапах. Потому что мне не нужно будет собирать каждый раз таблицу в удобоваримый для передачи дальнейшим обработчикам вид, например, в тот же json.

Link to comment
Share on other sites

  • 0
Проводя денормализацию. В кеше и хранятся денормализованные данные. А кэш иногда проще вообще не использовать, так как затраты на обновление кеша могут привысить затраты на обработку запроса базой.

Если затраты на обновление кеша у вас первышают работу с базой, значит пора уволить архитектора и пригласить того, кто хоть немного в этом понимает. И в создании кеша, и в его актуализации.

В чем проблема? Вам нужно всего лишь обновить n строк, где n - количество синонимов в группе. Это предсказуемое количество.

Искать вы это слово как будете в хранимом JSON-е? Скан всей таблицы без индекса, ага. У вас же хайлоад, миллионы записей данных... :facepalmxd:

Только весь прикол в том, что один запрос оффлайновый, а второй - онлайновый. И да, я получу адский профит на всех этапах. Потому что мне не нужно будет собирать каждый раз таблицу в удобоваримый для передачи дальнейшим обработчикам вид, например, в тот же json.

Еще раз, не мешаейте в кучу кеш и работу с данными. Хоть для этого найдите соображение. Что сначала проектируются данные и работа с ними, а потом, если это место становится узким - реализуют заранее продуманные заглушки по кешированию. По-этому нефиг лезть с кешированием данных в тему о структуре исходных данных и работе с ними. В 100% случаев обсуждаемых на этом форуме трудозатраты по созданию нормального кеша и обслуживание усложненного кода никогда не оправдают копеечный выигрыш, который тут предлагается.

Link to comment
Share on other sites

  • 0

Если затраты на обновление кеша у вас первышают работу с базой, значит пора уволить архитектора и пригласить того, кто хоть немного в этом понимает. И в создании кеша, и в его актуализации.

Почитайте про новую архитектуру Гугла. С их объемами это вполне реально.

Искать вы это слово как будете в хранимом JSON-е?

:rofl:

А кто вам сказал, что нужно искать именно в json'e? Вариант с двумя полями вас не устраивает? Одно поле - слово, второе - json. Ищется по первому полю, результат берется из второго.

Еще раз, не мешаейте в кучу кеш и работу с данными.

А я и не мешал. Это вы себе придумали что-то, потом спорите со своими фантазиями.

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

А как именно будет происходить работа с нормализованными данными, это уже не столь важно. Тут применять классическое решение и не заморачиваться: таблица-словарь со словами и таблица связей.

Link to comment
Share on other sites

  • 0
Почитайте про новую архитектуру Гугла. С их объемами это вполне реально.

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

А кто вам сказал, что нужно искать именно в json'e? Вариант с двумя полями вас не устраивает? Одно поле - слово, второе - json. Ищется по первому полю, результат берется из второго.

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

О том, что у вас будет отстутствовать хоть какая-то проверка консистенции данных, можно и не говорить, вы же понимаете это, да?

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

А как именно будет происходить работа с нормализованными данными, это уже не столь важно. Тут применять классическое решение и не заморачиваться: таблица-словарь со словами и таблица связей.

Да, в отличие от вас я прекрасно понял, что автор вообще нихрена не смыслит. И не стал показывать крутость знаний хайлоада, а объяснил на классическом SQL. Ваш вариант - всего лишь кеш. Вас спросили как данные хранить, а вы рассказли, как их кешировать. Да еще с отсылками на гипотетический хайлоад. Сначала нужно научится задачи классически решать, а потом уже читать про архитектуры хайлоадов и сувать их куда не попадя. Испугался одного джойна и засрал таблицу тоннами говна "денормализованных данных"... классика. Не нужна там таблица связей, LunatiK давно уже увидел самое простое решение, и выборка из него будет в один джойн таблицы на себя.

Спорить больше не о чем.

Link to comment
Share on other sites

  • 0

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

Этого в описании архитектуры нет. И при чем тут превышение трафика обновления кеша над скоростью запроса данных? :blink:

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

О том, что у вас будет отстутствовать хоть какая-то проверка консистенции данных, можно и не говорить, вы же понимаете это, да?

Итак, имеем две таблицы

| id | word | syn |

и | id | syn_id |

Существует два процесса - обновление данных и денормализация.

При обновлении мы должны найти слово в базе, изменить его значение word и обнулить syn. Вытаскиваем данные по синонимам слова.

При добавлении мы должны вставить новое слово. Найти все записи со словами-синонимами, и добавить их идентификаторы в таблицу связей.

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

Далее запускаем процедуру денормализации для списка синонимов и для искомого объекта, если это не удаление.

Вас спросили как данные хранить, а вы рассказли, как их кешировать.

Меня спрашивали как данные выводить, а не хранить.

Не нужна там таблица связей, LunatiK давно уже увидел самое простое решение, и выборка из него будет в один джойн таблицы на себя.

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

Слову "делать" синонимами могут быть слова "изготавливать" и "реализовывать", но вот слову "реализовывать" может быть синонимом слово "продавать". А "продавать" не является синонимом слово "делать".

Спорить больше не о чем.

Конечно не о чем. :rofl:

  • Like 1
Link to comment
Share on other sites

  • 0
Далее запускаем процедуру денормализации для списка синонимов и для искомого объекта, если это не удаление.
Только так и надо решать. Можно сразу хранить json-объект (вернее его текстовое представление)
А кэш иногда проще вообще не использовать, так как затраты на обновление кеша могут привысить затраты на обработку запроса базой.

Ну хорошо хоть перестали убеждать, что данные нужно прямо так и хранить. Теперь осталось научится рассказывать человеку как хранить данные, а потом, если нужно, рассказать как кешировать. А не рассказывать, что данные нужно сразу хранить кешированные (для понимания - денормализованные в данном случае = кешированные), не упомянув о том, как же их хранить изначально. Ибо решение о кешировании принимается исходя из архитектуры проекта, а не из задачи "как мне сделать".

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

Да, тогда или вторая таблица, как я писал выше, или дублирование слов в одной таблице как омонимов.

Edited by MiksIr
  • Like 1
Link to comment
Share on other sites

  • 0

Ну хорошо хоть перестали убеждать, что данные нужно прямо так и хранить.

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

Да, тогда или вторая таблица, как я писал выше, или дублирование слов в одной таблице как омонимов.

;)

Edited by s0rr0w
  • Like 1
Link to comment
Share on other sites

  • 0

Или я не прав, и есть более простые решения ?

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

Я что-то не очень понял куда там JOIN можно вставить, если для дискутирующих это очевидно - то покажите пример

slovo     | gruppa
-------------------
пить | 1
бухать | 1
колдырять | 1
квасить | 1
курить | 2
смолить | 2
дымить | 2
пыхать | 2
-------------------

Я это все прдставлял так:

запрос слово: 'квасить'

SELECT `slovo` FROM `table` WHERE `gruppa` = (SELECT `gruppa` FROM `table` WHERE `slovo` = 'квасить')

?

Link to comment
Share on other sites

  • 0

Таблицу можно джойнить саму на себя

SELECT t2.slovo FROM table t1 INNER JOIN table t2 ON (t1.group = t2.group) WHERE t1.slovo='квасить';

Как-то идея понятна, но рабочего примера для просветления не увидел

Осознал, прозрел.

Edited by LunatiK
Link to comment
Share on other sites

  • 0

Тогда вернусь к вопросу:

Потому что там JOIN надо применять. В моем варианте нужно найти всего одну строку и как есть отправить на обработку.

Чем плох JOIN? не уж-то большую нагрузку создаст? В Варианте с JSON будет избыточность данных, насколько она оправдана(Удобство ввода? Редактирования? С поиском и выводом всё ясно.) ?

Link to comment
Share on other sites

  • 0

Чем плох JOIN? не уж-то большую нагрузку создаст? В Варианте с JSON будет избыточность данных, насколько она оправдана(Удобство ввода? Редактирования? С поиском и выводом всё ясно.) ?

JOIN кушает ресурсы. И чем больше записей в таблице, тем больше с ним придется возиться.

Избыточность не страшна, так как на одну процедуру записи данных будут миллионы чтения. И что лучше, миллион раз применять JOIN и процедуру пост-обработки данных, или сделать это один раз и потом пользоваться результатами? Я за последний вариант.

Link to comment
Share on other sites

  • 0

SELECT `slovo` FROM `table` WHERE `gruppa` = (SELECT `gruppa` FROM `table` WHERE `slovo` = 'квасить')


SELECT `slovo` FROM `table` WHERE `gruppa` = (SELECT `gruppa` FROM `table` WHERE `slovo` = LIKE '%search%' || `gruppa` = int($_GET['gruppa']))

поиск+переход по ссылке ;)

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

Link to comment
Share on other sites

  • 0

Да быстро join будет работать, быстро. Нужно очень быстрое решение - берите сфинкс, скармливайте ему статьи с синонимами и ищите.

А то, что предлагает s0rr0w - это на пустом месте родить сотни мегабайт ненужных, дублированных данных ради неопределенной экономии.

Edited by MiksIr
Link to comment
Share on other sites

Join the conversation

You can post now and register later. If you have an account, sign in now to post with your account.
Note: Your post will require moderator approval before it will be visible.

Guest
Answer this question...

×   Pasted as rich text.   Paste as plain text instead

  Only 75 emoji are allowed.

×   Your link has been automatically embedded.   Display as a link instead

×   Your previous content has been restored.   Clear editor

×   You cannot paste images directly. Upload or insert images from URL.

 Share

×
×
  • Create New...

Important Information

We have placed cookies on your device to help make this website better. You can adjust your cookie settings, otherwise we'll assume you're okay to continue. See more about our Guidelines and Privacy Policy