Никита Липинский
403 сообщения
#17 лет назад
Товарищи, задался вопросом:
Интересуют примеры досок объявлений, в которых реализовано неограниченное колиество подкатегорий (хотя бы 4).

Пример:
Недвижимость
Квартиры
1-Комнатные
Новостройки

Интересуюсь потому что есть собственное решение, но оно кажется... несколько громоздким. Хочу посмотреть как сделали другие, а примеров в укрнете найти не могу (в рунете не искал - сижу на украинском трафике, но если дадите ссылку на .ru обязательно посмотрю).

Спасибо!

P.S. для администрации (невозможно форматировать текст - пробелы и табуляция съедаются)
Никита Липинский
403 сообщения
#17 лет назад
Неужели никто не видел такой доски объявлений?
Товарищи программисты, если не знаете сходу такого примера - напишите, как вы бы это реализовали на php + MySQL

VStudio? krab?
Никита Липинский
403 сообщения
#17 лет назад
VStudio: tnx
Евгений О.
2989 сообщений
#17 лет назад
С помощью php + MySQL это делается, также и при работе с любой базой данных. Создаем базу с описанием категорий, перебираем все нужные записи и выводим, например, в таблицу. Если категории должны содержать подкатегории, то надо определить заранее, как будет строиться древо: все категории/подкатегории будут содержаться в одной таблице, или для каждой категории/подкатегории будет отдельная таблица. Оба способа имеют и достоинства и недостатки. Как пример реализации можно посмотреть на . На сайте разделы реализованы в разных таблицах, на форуме - в одной таблице.
Станислав Малкин
1410 сообщений
#17 лет назад
Это не каноническая форма - это нормальная форма, полученная в процессе нормализации. Далеко не обязательно приводить базу к нормальным формам, а тем более к нормальным формам высших порядков при больших базах - ибо теряется производительность...
Вадим Т.
3240 сообщений
#17 лет назад
Цитата ("ArtLab"):
это не каноническая форма - это нормальная форма, полученная в процессе нормализации. Далеко не обязательно приводить базу к нормальным формам, а тем более к нормальным формам высших порядков при больших базах - ибо теряется производительность...


Оптимальной для 99% проектов считается третья нормальная форма. Формы более высоких порядков - уже специальные, применяются для тех или иных специфических задач. Например, для систем работающих под повышенной нагрузкой иногда наоборот имеет смысл проводить денормализацию - дублирование полей, таблиц и т.д. Обычно, классически, неограниченное количество таблиц используется в таких системах, в которых пользователям предоставляется возможность строить свои структуры данных. Но есть и другое семейство задач...

Спам-машина. Лично я - противник спама, просто сейчас рассматриваю как академический пример. В самом примитивном варианте достаточно четырех таблиц: таблица e-mails, таблица клиентов, таблица рекламных компаний-рассылок, и таблица-хистори в которой содержится что кому и когда было послано, чтобы одно и то же не отсылать дважды в рамках одной рекламной компании. Пусть есть хотя бы эти 4 таблицы, реально же будет их штук 20 типа bounced e-mails, исключения, релеи и т.д., но пока не будем это рассматривать. Итак, есть 4 таблицы. Каков будет их размер? Допустим у нас есть очень мало, всего лишь 300 тыс. e-mails. Посчитайте-ка размер хистори если будет хотя бы 20 клиентов. А если у этих клиентов будет не одна, а хотя бы по 5 рекламных компаний? Тут классическая БД в 3-й нормальной форме умрет. По крайней мере любой типичный запрос типа "были ли отослан e-mail такой-то в рекламной компании такой-то" будет вгонять БД в долгую задумчивость (не забываем что БД находится под постоянной нагрузкой). В общем, денормализация на таких проектах - это must have, конечно особенно эффективно будет если разнести эту базу данных на большое количество хостов.

В данном проекте с подкатегориями, про который идет речь в этой ветке форума, скорее всего это делать не нужно, хотя все-таки зависит от природы данных... Вот недавно делали проект для риелтеров, там очень все неоднозначно было, пришлось делать доплнительные таблицы-индексаторы. В общем, если хотите - могу предложить/разработать структуру данных для Вашего проекта, обращайтесь.
Вадим Т.
3240 сообщений
#17 лет назад
Цитата ("Shevron"):
Да точно, форма нормализации, ошибся. Но здесь разговор не идет о производительности. Кстати о производительности года четыре назад специально задался вопросом что производительней: выборка из таблицы с небольшим числом записей или выборка из таблицы с большим числом записей - оказалось почти одинаково, если заданы правильно индексы. Тестировал на MS SQL 2000, Oracle 8i и Интербейзе 5.


Так и есть, время на выборку по индексированным полям не будет значительно зависеть от размера таблиц, если а) выборка линейная; б) затрагивает малое количество таблиц, лучше одну; в) выборка неблокирующая; г) БД находится не под нагрузкой.

Например, если система под нагрузкой, и если постоянно таблицы модифицируются (соответственно постоянно перестраиваются индексы), то время выборки будет очень сильно зависеть от размера таблиц!

====
UPD. Имею ввиду, если система под нагрузкой, и данные в ней постоянно читаются и модифицируются. То есть добавлятся, удаляются, изменяются, блокирутся другими транзакциями, еtc.
Раду М.
159 сообщений
#17 лет назад
Цитата ("tvv"):
Цитата ("ArtLab"):
Спам-машина. Лично я - противник спама, просто сейчас рассматриваю как академический пример. В самом примитивном варианте достаточно четырех таблиц: таблица e-mails, таблица клиентов, таблица рекламных компаний-рассылок, и таблица-хистори в которой содержится что кому и когда было послано, чтобы одно и то же не отсылать дважды в рамках одной рекламной компании. Пусть есть хотя бы эти 4 таблицы, реально же будет их штук 20 типа bounced e-mails, исключения, релеи и т.д., но пока не будем это рассматривать. Итак, есть 4 таблицы. Каков будет их размер? Допустим у нас есть очень мало, всего лишь 300 тыс. e-mails. Посчитайте-ка размер хистори если будет хотя бы 20 клиентов. А если у этих клиентов будет не одна, а хотя бы по 5 рекламных компаний? Тут классическая БД в 3-й нормальной форме умрет. По крайней мере любой типичный запрос типа "были ли отослан e-mail такой-то в рекламной компании такой-то" будет вгонять БД в долгую задумчивость (не забываем что БД находится под постоянной нагрузкой). В общем, денормализация на таких проектах - это must have, конечно особенно эффективно будет если разнести эту базу данных на большое количество хостов.


Чудеса, о каком сервере баз данных вы говорите? Можете привести схему данных и пример кода производящий выборки? Что-то не верится что сервер баз данных не справится с вашим запросом на 300 тысячах записях, если конечно это не какой-то там FoxPro или MySQL. В тестировании про которое я говорил выше использовалась база данных с информацией о биллинге интернет трафика сотрудниками крупной компании, примерно по 2 милиона записей в месяц и ничего не умирало, причем MS SQL тестировался на живой базе, как вы говорите под нагрузкой. Скорее всего в вашем примере узкое место связаное не с "Тут классическая БД в 3-й нормальной форме умрет" как вы говорите, а с (в порядке вероятности): не верно спланированной базой данных или отсутсвием правильных индексов, непоизводительным сервером баз данных, неоптимально написанном коде, неподходящей платформой для выполнения этих задач.
Вадим Т.
3240 сообщений
#17 лет назад
Цитата ("Shevron"):
Чудеса, о каком сервере баз данных вы говорите? Можете привести схему данных и пример кода производящий выборки? Что-то не верится что сервер баз данных не справится с вашим запросом на 300 тысячах записях, если конечно это не какой-то там FoxPro или MySQL. В тестировании про которое я говорил выше использовалась база данных с информацией о биллинге интернет трафика сотрудниками крупной компании, примерно по 2 милиона записей в месяц и ничего не умирало. Скорее всего в вашем примере узкое место связаное не с "Тут классическая БД в 3-й нормальной форме умрет" как вы говорите, а с (в порядке вероятности): не верно спланированной базой данных или отсутсвием правильных индексов, непоизводительным сервером баз данных, неоптимально написанном коде, неподходящей платформой для выполнения этих задач.


Пожалуйста обратите внимание. 300 тыс в данном примере - это только лишь e-mails! А где хранить что кому и когда было отослано? В своем примере я просил подсчитать, Вы поспешили, не подсчитали... Считаем: 300000 emails * 20 клиентов * 5 компаний = 30 МИЛЛИОНОВ записей. Это уже неплохо. А если будет не 20 клиентов, а 100 клиентов?
Раду М.
159 сообщений
#17 лет назад
Цитата ("tvv"):
Цитата ("Shevron"):
Чудеса, о каком сервере баз данных вы говорите? Можете привести схему данных и пример кода производящий выборки? Что-то не верится что сервер баз данных не справится с вашим запросом на 300 тысячах записях, если конечно это не какой-то там FoxPro или MySQL. В тестировании про которое я говорил выше использовалась база данных с информацией о биллинге интернет трафика сотрудниками крупной компании, примерно по 2 милиона записей в месяц и ничего не умирало. Скорее всего в вашем примере узкое место связаное не с "Тут классическая БД в 3-й нормальной форме умрет" как вы говорите, а с (в порядке вероятности): не верно спланированной базой данных или отсутсвием правильных индексов, непоизводительным сервером баз данных, неоптимально написанном коде, неподходящей платформой для выполнения этих задач.


Пожалуйста обратите внимание. 300 тыс в данном примере - это только лишь e-mails! А где хранить что кому и когда было отослано? В своем примере я просил подсчитать, Вы поспешили, не подсчитали... Считаем: 300000 emails * 20 клиентов * 5 компаний = 30 МИЛЛИОНОВ записей. Это уже неплохо. А если будет не 20 клиентов, а 100 клиентов?


Минуточку, что-то я вас не понял, как это вы так подсчитали количество записей которыми оперирует SQL запрос? Приведите пожалуйста его код и структуру базы данных. А то получается что емайлов у вас 300000 а писем на них нужно разослать 30 милионов? Допустим даже так, но причем здесь сервер баз данных, он все равно обработает 300000 записей, не больше и не меньше. Не ужели вы пологаете, что если разнесете даные по куче таблиц, количество записей уменьшится?

По мойму у вас узкое место не в работе SQL сервера, а в отсылке емайлов. Вы конечно помните, что отсылка одного емала затрагивает на много больше времени, нежели выборка записи из базы данных с информацией об этом емайле. Я понимаю что могут быть задачи, которые сильно давят на производительность SQL сервера, но говорить как вы утверждаете "классическая БД в 3-й нормальной форме умрет" сильно опосаюсь. В этом суть вопроса.
Вадим Т.
3240 сообщений
#17 лет назад
Цитата ("Shevron"):

Минуточку, что-то я вас не понял, как это вы так подсчитали количество записей которыми оперирует SQL запрос? Приведите пожалуйста его код и структуру базы данных. А то получается что емайлов у вас 300000 а писем на них нужно разослать 30 милионов? Допустим даже так, но причем здесь сервер баз данных, он все равно обработает 300000 записей, не больше и не меньше.


Ну смотрите. Есть 300 тыс. e-mails. Эта база данных e-mail продается клиентам, заказывающих рекламные компании по рассылке, этим же клиентам предоставляется интерфейс спам-машины. То есть, каждый клиент, который купил аккаунт, может заказать разослать на эти 300 e-mails свои спам письма.

То есть, допустим Вы купили аккаунт. Задали в специальной форме определили письмо, которое должно уйти всем 300 тыс. Это Вы инициировали рекламную кампанию. Кстати некоторые заказывают сразу 10 кампаний, или повторяют кампании каждые 2 недели... То есть, КАЖДАЯ Ваша кампания по спам-рассылке грузит активную базу данных доплнительными 300 тыс. новыми записями. А ведь таких клиентов как Вы может обслуживаться десятки и сотни. И e-mails может быть не 300 тыс, а например 5 млн.

Конечно, когда кампания завершается, background job будет переносить эти данные в архив, но все равно если система предоставляет интерфейс одновременно сотням клиентам, то число записей в активной таблице будет равно <количество_клиентов> * <количество_активных_кампаний> * <количество_emails>.

Эту описанную структуру данных из 4х таблиц приводить не буду, ее быть не может в живом виде так как это - пример, который в 3й нормальной форме жить не может по описанным мной причинам. Задача решается совсем другими способами, БД проектируется из расчета на распределенную обработку данных.

===
UPD. Сорри, поправка, более правильно будет RECORDS = <количество_активных_кампаний> * <количество_emails>, тут <количество_активных_кампаний> - это сумма ВСЕХ активных кампаний ВСЕХ клиентов. Но итог тот же, и выводы те же.
Вадим Т.
3240 сообщений
#17 лет назад
Цитата ("Shevron"):
Минуточку, что-то я вас не понял, как это вы так подсчитали количество записей которыми оперирует SQL запрос? Приведите пожалуйста его код и структуру базы данных. А то получается что емайлов у вас 300000 а писем на них нужно разослать 30 милионов? Допустим даже так, но причем здесь сервер баз данных, он все равно обработает 300000 записей, не больше и не меньше. Не ужели вы пологаете, что если разнесете даные по куче таблиц, количество записей уменьшится?


Ну как мне еще Вам объяснить...

Продолжу. Действительно, в этом примере мы обработаем только лишь 300000 записей. Но - лишь в таблице e-mails. Эта таблице не изменяется. Я же имею виду таблицу, в которую заносится информация: что, кому и кода было отослано. Именно она - узкое место системы, и именно в ней будут все эти десятки-сотни миллионов записей, если структура БД будет приведена к 3й нормальной форме.
Раду М.
159 сообщений
#17 лет назад
Цитата ("tvv"):
То есть, допустим Вы купили аккаунт. Задали в специальной форме определили письмо, которое должно уйти всем 300 тыс. Это Вы инициировали рекламную кампанию. Кстати некоторые заказывают сразу 10 кампаний, или повторяют кампании каждые 2 недели... То есть, КАЖДАЯ Ваша кампания по спам-рассылке грузит активную базу данных доплнительными 300 тыс. новыми записями.


Это как так? Вообще-то одна моя рекламная компания грузит вашу базу данных, ровно на одну запись в таблице рекламных компаний. Если при каждой компании вы создаете 300 тыс записей, которые копируются из-одного места в другое, то здесь явное нарушение третей формы, так как данные не должны дублироваться. То есть, вы форму нарушили, увидели кучу проблем, а потом говорите что форма умерла :-)

Скажите, кто вам планировал такие бизнес-процессы и разрабатывал код, где подписка на "рекламную компанию" дублирует 300 тысяч записей?

Цитата ("tvv"):
Конечно, когда кампания завершается, background job будет переносить эти данные в архив, но все равно если система предоставляет интерфейс одновременно сотням клиентам, то число записей в активной таблице будет равно <количество_клиентов> * <количество_активных_кампаний> * <количество_emails>.


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

Цитата ("tvv"):
Эту описанную структуру данных из 4х таблиц приводить не буду, ее быть не может в живом виде так как это - пример, который в 3й нормальной форме жить не может по описанным мной причинам. Задача решается совсем другими способами, БД проектируется из расчета на распределенную обработку данных.


Давайте не будет говорить метаформами и абстракциями, математика наука точная. Я сомневаюсь что вы совершите переворот проектом рассылки емайлов. Предьявите вашу схему базы данных и код выборки, который вы произвели так как по вашему мнению третья форма не удовлетворила потребности, чтобы народ расценил его красоту. Иначе разговор сводится к неподвержденным абстракциям и становится не интересным.
Вадим Т.
3240 сообщений
#17 лет назад
Цитата ("Shevron"):
Это как так? Вообще-то одна моя рекламная компания грузит вашу базу данных, ровно на одну запись в таблице рекламных компаний. Если при каждой компании вы создаете 300 тыс записей, которые копируются из-одного места в другое, то здесь явное нарушение третей формы, так как данные не должны дублироваться. То есть, вы форму нарушили, увидели кучу проблем, а потом говорите что форма умерла :-)


Конечно же сразу 300 тыс. никуда не будет копироваться (хотя иногда в этом смысл есть, но сейчас ресь не об этом). Давайте с другой стороны подойдем. Вопрос. Где Вы будите хранить информацию о том, на какой e-mail, в какой рекламной кампании, и когда был отправлен? И сколько будет этих записей в хистори?

===
UPD А без хистори тут нельзя, Вы ведь не станете отправлять эти 300 тыс. e-mails в одном потоке, это процесс, растянутый на продолжительное время, да и статистика доставлено/отказано и т.д. тоже желательно должна накапливаться где-то (но статистику а нашем академическом примере можно не учитывать чтобы не усложнять задачу).
Раду М.
159 сообщений
#17 лет назад
Цитата ("tvv"):
Цитата ("Shevron"):
Это как так? Вообще-то одна моя рекламная компания грузит вашу базу данных, ровно на одну запись в таблице рекламных компаний. Если при каждой компании вы создаете 300 тыс записей, которые копируются из-одного места в другое, то здесь явное нарушение третей формы, так как данные не должны дублироваться. То есть, вы форму нарушили, увидели кучу проблем, а потом говорите что форма умерла :-)


Конечно же сразу 300 тыс. никуда не будет копироваться (хотя иногда в этом смысл есть, но сейчас ресь не об этом). Давайте с другой стороны подойдем. Вопрос. Где Вы будите хранить информацию о том, на какой e-mail, в какой рекламной кампании, и когда был отправлен? И сколько будет этих записей в хистори?


Отношение многие ко многим вам знакомо? Но вы не отвлекайтесь от темы, хочется посмотреть схему вашей базы данных, так как мне это очень интересно с проффесиональной точки зрения. Думаю многие кто занимается разработками баз данных также захотят это увидеть, так как не часто встретишь проекты, где утверждаются такие переворотные высказывания. Если не нет, то и разговора дальше не будет, так как мы начнем грузить друг друга лексемами.
Вадим Т.
3240 сообщений
#17 лет назад


Вот, если кому-то трудно представить схему БД простейшего спам-рассыльщика из 4х таблиц о которых мы говорим, я эту схему только что нарисовал... Обратите внимание, эта схема выполнена именно в 3й нормальной форме. Спор был о том, что не всегда 3я нормальная форма полезна, и часто от нее необходимо избавляться, проводя денормализацию, возможно с дублированием полей или даже целых таблиц.

Итак, мы имеем таблицу sp_email в которой 300 тыс. записей (это очень мало, обычно раз в 20 больше, но допустим спамеры у нас начинающие). Мы имеем всего лишь 20 клиентов у этого спамера, у которых запущено по 5 рекламных кампаний (то есть суммарно 100 кампаний). Сколько будет записей в таблице sp_email_history?

Записи в sp_email_history можно добавлять сразу после инициации кампании (я рекомендую, иначе на каждый email-кандидат на отправку придется делать запрос "есть ли этот e-mail в таблице sp_email_history?" что не эффективно), можно последовательно добавлять по мере отправки (не рекомендую, массовые inserts будут постоянно вызывать перестройку индексов) - но это неважно, независимо от этого в таблице sp_email_history будут десятки миллионов записей.

То есть вывод - используя 3ю нормальную форму на этой задаче мы получаем таблицу-монстра, частые запросы к которой положат любую БД. Единственный выход - денормализация, а еще лучше - денормализация + распределение нагрузки на несколько хостов.