SQLinfo.ru - Все о MySQL

Форум пользователей MySQL

Задавайте вопросы, мы ответим

Вы не зашли.

#1 21.06.2009 18:02:47

zales
Участник
Зарегистрирован: 21.06.2009
Сообщений: 16

Выбор оптимальной структуры для хранения списка объявлений (Partitioning)

Дано:
Есть таблица объявлений.
Любое объявление принадлежит определенному разделу (перечень разделов конечен и может быть реализован как перечисление).

Примерная структура таблицы объявлений

ad
----------------------------------------------
ad_id INT
section ENUM('AUTO','MOTO','PARTS')
created DATETIME
about MEDIUMTEXT
createdby INT

Надо:
Известно, что поиск объявлений пользователями будет осуществляться строго по разделам соответственно имеет смысл произвести разбиение таблицы по разделам (поле section). Кроме того, каждому разделу объявлений в исходной таблице выделен диапазон номеров (ad_id). Например, для запчастей [1001-5000], для мототехники [5001-7000] и т.д.

Вопрос состоит в следующем:
1. Можно ли пользоваться разбиениями как отдельными таблицами, то есть сохранять записи в своем диапазоне ид-номеров с автоматическим инкрементом в зависимости от раздела. Например, если я создаю первое объявление в разделе запчасти, то создается запись с ид=1001, если создаю первую запись в разделе мототехника, то ид=5001 и т.д.
Я читал, что если использовать составной ключ (section, ad_id), то ad_id нумеруется с 1 для каждого раздела, то есть {1:'AUTO':...} {1:'MOTO':...} {1:'PARTS':...}
a необходимо {7001:'AUTO':...} {5001:'MOTO':...} {1001:'PARTS':...} {7002:'AUTO':...} и т.д.

2. Если первое неверно, то каким образом это можно реализовать

Неактивен

 

#2 22.06.2009 11:32:16

Magz
Гуру
Откуда: Москва
Зарегистрирован: 18.09.2007
Сообщений: 112

Re: Выбор оптимальной структуры для хранения списка объявлений (Partitioning)

Во-первых, если Вы предполагаете, что количество объявлений будет в районе 10 000 (этот вывод я делаю исходя из тех диапазонов id, которые Вы привели), то можно просто использовать одну таблицу и не париться.
Второй вариант оптимизации по Вашим условиям (поиск будет осуществляться строго по разделам, поле sectiion Вы задаете как жестко заданный ENUM) - сделать для каждого раздела свою таблицу.
Это гораздо проще, чем заморчиваться с диапазонами id, а производиельности на первое время (пока сайт будет раскручиваться) хватит за глаза. Плюс, даст возможность развиваться в будущем.

Неактивен

 

#3 22.06.2009 13:06:37

zales
Участник
Зарегистрирован: 21.06.2009
Сообщений: 16

Re: Выбор оптимальной структуры для хранения списка объявлений (Partitioning)

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

В продолжение темы хотелось бы задать еще несколько вопросов.
1. Необходимо реализовать поиск по параметрам (марка, модель, тип двигателя, дополнительные опции: кондиционер, круиз-контроль и т.д.) Изначально думал об использовании модели EAV, но услышал много нелестного и решил отказаться. Хотелось бы услышать и ваше мнение. smile [в моей задаче набор параметров конечен и добавление новых возможно только модератором]
2. Параметры хранятся в отдельных таблицах car_ad_param_values (для авто), tyres_ad_param_values (для шин) и т.д.

Вопрос состоит в следующем: как оптимальней хранить булевы значения в виде BITS(M) или аналога или для каждого заводить отдельное поле TINYINT(1)

Неактивен

 

#4 22.06.2009 14:55:18

LazY
_cмельчак
MySQL Authorized Developer and DBA
Зарегистрирован: 02.04.2007
Сообщений: 849

Re: Выбор оптимальной структуры для хранения списка объявлений (Partitioning)

Вообще правильно говорит Magz.
Я бы все же на вашем месте пошел дальше сделал третью нормальную форму - section INT вместо ENUM, (отдельную таблицу с разделами). Так будет лучше масштабироваться (представьте, что требования изменились, и надо 20 разделов; и еще так будет легче объявления между разделами перекидывать, если вдруг понадобится, ну и т.п.)

Неактивен

 

#5 22.06.2009 16:08:01

Magz
Гуру
Откуда: Москва
Зарегистрирован: 18.09.2007
Сообщений: 112

Re: Выбор оптимальной структуры для хранения списка объявлений (Partitioning)

zales, модель EAV предоставляет большую гибкость, но проигрывает в скорости на абстрактных тестовых данных. Плюс, гемор в реализации. Если параметры могут добавляться администратором, то значит набор не конечен априори smile Я бы для Вашего случая не брал бы вчистую эту схему. Я бы сделал таблицу возможных параметров и свзяь с таблицей объекта вида "один объект ко многим параметрам". Судя по всему, Вы так и сделали, хотя фраза "Параметры хранятся в отдельных таблицах..." без структуры таблицы не дает полной уверенности smile
По поводу boolean. Я предпочитаю не испоьзовать boolean вообще. В свое время на Почте России оптимизировал базу, где у двух миллионов записей об отправлениях сделали boolean поле "Доставлено". Запрос "получи что-то среди недоставленных" выполнялся больше 30 секунд. После этого boolean поля недолюбливаю smile

Неактивен

 

#6 22.06.2009 18:14:16

zales
Участник
Зарегистрирован: 21.06.2009
Сообщений: 16

Re: Выбор оптимальной структуры для хранения списка объявлений (Partitioning)

to LazY: в плане масштабируемости согласен, а в плане производительности какой вариант лучше? (внешний ключ + словарь) или перечисление
to Magz: по поводу нескольких таблиц параметров имелось в виду, что
автообъявление : параметры для авто [связь 1:n]
объявление о продаже запчастей : параметры для запчасти  [связь 1:n]

то есть boolean отпадает из практического опыта smile
может есть опыт использования битовой маски?
или сегодня еще прочитал про возможность хранения в виде XML такого рода параметров в одном поле БД (альтернатива JSON)

Неактивен

 

#7 22.06.2009 18:28:56

zales
Участник
Зарегистрирован: 21.06.2009
Сообщений: 16

Re: Выбор оптимальной структуры для хранения списка объявлений (Partitioning)

Вот примерная схема автообъявлений (без запчастей и без разделов пока)


Прикрепленные файлы:
Attachment Icon auto.png, Размер: 22,695 байт, Скачано: 777

Неактивен

 

#8 22.06.2009 21:29:09

zales
Участник
Зарегистрирован: 21.06.2009
Сообщений: 16

Re: Выбор оптимальной структуры для хранения списка объявлений (Partitioning)

Переработал немного структуру. Обязательные при заполнении и основные при поиске атрибуты перенес в таблицу объявлений. Как по вашему какое решение лучше это или предыдущее.


Прикрепленные файлы:
Attachment Icon auto.png, Размер: 19,324 байт, Скачано: 839

Неактивен

 

#9 24.06.2009 11:39:51

Magz
Гуру
Откуда: Москва
Зарегистрирован: 18.09.2007
Сообщений: 112

Re: Выбор оптимальной структуры для хранения списка объявлений (Partitioning)

Первая значительно лучше второй, но я бы не делал ни так, ни так smile Если не говорить о глобальной реструктуризации, то я бы посоветовал следующее (по первой схеме):
1. Я бы не рекомендовал навешивать на БД реализацию бизнес-логики. Обязательность/необязательность каких-то атрибутов при заполнении - это именно бизнес-логика, которая может меняться со временем при неизменности самих данных. Это относится как к автомобилю, так и к пользователю. Связей "один к одному" существовать без особой необходимости не должно, а у Вас такой необходимости нет.
2. Вы уверены, что информацию о пользователе (телефонах и т.д.) нужно дублировать? У Вас возникнут проблемы, если пользователь поменяет номер телефона.
3. Я бы убрал country_id из car_ad_param_values - мне кажется, что запрос типа "жигули по всей России" или "Вольво в любом городе Украины" маловероятны, а страну Вы всегда получите через город.

Отредактированно Magz (24.06.2009 11:55:05)

Неактивен

 

#10 24.06.2009 11:53:55

Magz
Гуру
Откуда: Москва
Зарегистрирован: 18.09.2007
Сообщений: 112

Re: Выбор оптимальной структуры для хранения списка объявлений (Partitioning)

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

Неактивен

 

#11 24.06.2009 12:01:07

zales
Участник
Зарегистрирован: 21.06.2009
Сообщений: 16

Re: Выбор оптимальной структуры для хранения списка объявлений (Partitioning)

1. В первом случае разделение таблицы объявлений на две (car_ad, car_ad_stats) было вызвано следующими соображениями: использоваться будет MyISAM, поэтому статистика просмотров страниц объявлений будет изменяться только в таблице car_ad_stats (last_update, hits), (я не большой специалист в БД), но так рекомендуют делать (может я слишком доверчивый smile. По поводу user_info я согласен.
2. Что касается  информации в объявлении смысл следующий: если пользователь не заполнил поля при создании объявления, то берутся данные из профиля, в противном случае те, которые он ввел при оставлении объявления. Так как часто пользователь хочет оставить информацию с др.телефонами.
3. согласен, избыточная информация.
4. Magz, если не так и не так, то если не секрет как? smile

Неактивен

 

#12 24.06.2009 13:36:07

zales
Участник
Зарегистрирован: 21.06.2009
Сообщений: 16

Re: Выбор оптимальной структуры для хранения списка объявлений (Partitioning)

to Magz: когда писал сообщение, не видел ваш последний пост.
Если несколько углубиться в ТЗ, то пользователь при оставлении объявления ДОЛЖЕН и МОЖЕТ оставить следующие параметры:
1. (основные) марка, модель, год выпуска, тип и объем двигателя, коробка, привод, кузов, телефон, цену, город + фото  ДОЛЖЕН
2. (дополнительные) указать опции + краткое резюме  МОЖЕТ

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

Уже неделю волнует вопрос организации поиска по дополнительным параметрам (вопрос о битовых масках). Читаю сообщения здесь на форуме, на хабре и т.д.: каждый отстаивает свою точку зрения (были предложения хранить как SET, как INT, как TEXT [большое колво параметров]), но это все на уровне фраз. Все же интересует мнение людей, которые реализовывали подобное в своих проектах. Может есть информация, где почитать НОРМАЛЬНУЮ документацию на тему.

Неактивен

 

#13 24.06.2009 13:37:24

zales
Участник
Зарегистрирован: 21.06.2009
Сообщений: 16

Re: Выбор оптимальной структуры для хранения списка объявлений (Partitioning)

to Magz: и еще вопрос. Почему вам второй вариант нравится меньше, чем первый?

Неактивен

 

#14 24.06.2009 16:47:27

Magz
Гуру
Откуда: Москва
Зарегистрирован: 18.09.2007
Сообщений: 112

Re: Выбор оптимальной структуры для хранения списка объявлений (Partitioning)

Второй вариант нравится меньше, потому что там произошло нерациональное (на мой взгляд) разделение таблиц на связи "один к одному". Завтра, например, поменяются требования и "краткое резюме" станет обязательным. И что, Вы будете переносить поле из однойтаблицы в другую?
По поводу структуры и по поводу поиска. Каждая структура, каждый метод хорош, но хорош по своему. Под каждую задачу выбирается оптимальный способ решения данной задачи, вот и все. А вот как выбрать оптимальный - это как раз зависит от опыта. Я вечером попробую набросать примерную схему, которую я бы использовал для такой задачи, но это не будет истина в последней инстанции. Это всего лишь еще один вариант. И выбирать Вам.
Маленький совет из опыта. Нужно идти от простого  сложному. Если сейчас будущее проекта не ясно, то нужно решать только те задачи, которые стоят перед Вами сейчас.

Неактивен

 

#15 24.06.2009 22:35:54

Magz
Гуру
Откуда: Москва
Зарегистрирован: 18.09.2007
Сообщений: 112

Re: Выбор оптимальной структуры для хранения списка объявлений (Partitioning)

Таблица Autos - данные об автомобиле, таблица Options - дополнительные опции. Разделение простое: если про что-то можно сказать "есть или нету" (например, магнитола, тонировка, литые диски, сигнализация) - то это в Options. Все остальное - в Autos. Соединяются через связь "многие-ко-многим" (AutoOptions). Выбор обусловлен тем, что подавляющее большинство запросов не будет использовать опции вообще, а будут ограничиваться данными из таблицы Autos. А положительный эффект для проекта от простоты реализации данной схемы перекроет отрицательный из-за сложных запросов.
По повод цены - ИМХО, никто до копеек или центов цену указывать не будет, поэтому предлагаю цену делать целым числом.
Таблица Adverts - данные об объявлении: кто подал, когда. Выделил отдельно от Autos (помимо более точного соответствия предметной области), так как сортировать наверняка придется по дате выдачи. Если эту дату "запихнуть" в Autos, то будут пробмы с индексами. К тому же, мы делаем независимым текущее состояние рынка (пул всех объявлений) и историю рынка (пул всех автомобилей). Это нам позволит строить аналитику по изменению цен, отследить путь машины (например, одну и ту же машину могут продавать несколько раз), оценивать машины путем сравнения.
При добавлении объявлений по запчастям, я бы в таблицу "Adverts" добавил бы поле id_запчасть и отдельную таблицу по аналогии с Autos. Необходимости получения сразу объявлений и по запчастям, и по машинам нет - в поиске мы четко разграничиваем области, а в управлении зависит от интерфейса. Я бы тоже разгарничил. В любом случае, ориентироваться стоит на поиск - он происходит в сотни раз чаще, чем операции по управлению объявлениями.
Теперь про пользователей и телефоны. Все телефоны выносим в отдельную таблицу. Пользователь добавляет нужное количество телефонов (например, 5). Потом дает 5 объявлений - каждое на свой телефон. Реализуется с помощью бизнес-логики, а хранятся ссылки на телефон. Это позволяет избежать дублирования информации при созранении возможности давать объявления на разные номера. Так же, позволит избежать повторных регистраций одного и того же человека - под разными логинам не может быть одинаковых телефонов.

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


SELECT a.id, a.Description
FROM Autos a FORCE INDEX (PRIMARY)
    JOIN AutoOptions ao ON (a.id = ao.id_auto AND ao.id_option = 2)
    JOIN AutoOptions ao2 ON (a.id = ao2.id_auto AND ao2.id_option = 4)
    JOIN AutoOptions ao3 ON (a.id = ao3.id_auto AND ao3.id_option = 3)
    JOIN Adverts av ON av.id_auto = a.id
WHERE  ao.id_auto = ao2.id_auto AND ao.id_auto = ao3.id_auto AND a.id_auto_brand = 1
ORDER BY av.AddDate
 

В этом запросе мы выбираем "все вольво (a.id_auto_brand = 1), которые имеют ДВД-магнитолу (ao.id_option = 2), литые диски (ao2.id_option = 4) и тонировку (ao3.id_option = 3).

Код:

mysql> EXPLAIN
    -> SELECT a.id, a.Description
    -> FROM Autos a FORCE INDEX (PRIMARY)
    ->  JOIN AutoOptions ao ON (a.id = ao.id_auto AND ao.id_option = 2)
    ->  JOIN AutoOptions ao2 ON (a.id = ao2.id_auto AND ao2.id_option = 4)
    ->  JOIN AutoOptions ao3 ON (a.id = ao3.id_auto AND ao3.id_option = 3)
    ->  JOIN Adverts av ON av.id_auto = a.id
    -> WHERE  ao.id_auto = ao2.id_auto AND ao.id_auto = ao3.id_auto AND a.id_auto_brand = 1
    -> ORDER BY av.AddDate;
+----+-------------+-------+--------+-------------------+----------+---------+---------------------------+------+-----------------------------+
| id | select_type | table | type   | possible_keys     | key      | key_len | ref                       | rows | Extra                       |
+----+-------------+-------+--------+-------------------+----------+---------+---------------------------+------+-----------------------------+
|  1 | SIMPLE      | av    | index  | id_index,NewIndex | NewIndex |      12 | NULL                      |    4 | Using index; Using filesort |
|  1 | SIMPLE      | a     | eq_ref | PRIMARY           | PRIMARY  |       4 | db_alco.av.id_auto        |    1 | Using where                 |
|  1 | SIMPLE      | ao2   | eq_ref | PRIMARY           | PRIMARY  |       8 | db_alco.a.id,const        |    1 | Using index                 |
|  1 | SIMPLE      | ao3   | eq_ref | PRIMARY           | PRIMARY  |       8 | db_alco.a.id,const        |    1 | Using index                 |
|  1 | SIMPLE      | ao    | eq_ref | PRIMARY           | PRIMARY  |       8 | db_alco.ao2.id_auto,const |    1 | Using where; Using index    |
+----+-------------+-------+--------+-------------------+----------+---------+---------------------------+------+-----------------------------+

Но, повторюсь, я думаю, что такой запрос будет редким.

Статистику просмотра объявления Вы правильно выделили в отдельную таблицу, я ее не стал показывать на схеме, но сделал бы так же.

Отредактированно Magz (24.06.2009 22:43:48)


Прикрепленные файлы:
Attachment Icon autos.jpg, Размер: 85,174 байт, Скачано: 831

Неактивен

 

#16 24.06.2009 22:44:25

Magz
Гуру
Откуда: Москва
Зарегистрирован: 18.09.2007
Сообщений: 112

Re: Выбор оптимальной структуры для хранения списка объявлений (Partitioning)

Вот дамп моей структуры без таблиц для пользователя.

Отредактированно Magz (24.06.2009 22:44:37)


Прикрепленные файлы:
Attachment Icon auto_dump.sql.gz, Размер: 1,354 байт, Скачано: 1,339

Неактивен

 

#17 24.06.2009 23:38:19

zales
Участник
Зарегистрирован: 21.06.2009
Сообщений: 16

Re: Выбор оптимальной структуры для хранения списка объявлений (Partitioning)

Как сказал один киноактер: "Приятно общаться с умными людьми".
Все лаконично, по делу и с примерами. smile Magz, спасибо, что потратили свое время на это.

Я только не понял, что вы имели в виду, когда говорили о запчастях:
>> "При добавлении объявлений по запчастям, я бы в таблицу "Adverts" добавил бы поле id_запчасть и отдельную таблицу по аналогии с Autos. Необходимости получения сразу объявлений и по запчастям, и по машинам нет - в поиске мы четко разграничиваем области, а в управлении зависит от интерфейса."

Неактивен

 

#18 25.06.2009 10:50:13

Magz
Гуру
Откуда: Москва
Зарегистрирован: 18.09.2007
Сообщений: 112

Re: Выбор оптимальной структуры для хранения списка объявлений (Partitioning)

Пожалуйста smile

zales написал:

Я только не понял, что вы имели в виду, когда говорили о запчастях:
>> "При добавлении объявлений по запчастям, я бы в таблицу "Adverts" добавил бы поле id_запчасть и отдельную таблицу по аналогии с Autos. Необходимости получения сразу объявлений и по запчастям, и по машинам нет - в поиске мы четко разграничиваем области, а в управлении зависит от интерфейса."

Чтобы добавить возможность размещать объявления по запчастям, нужно сделать таблицу Spares в которой будут все атрибуты запчастей. В таблицу Adverts добавляем поле id_spare, которое ссылается на id нужной запчасти в таблице Spares. Если объявление о продаже авто, то заполняется поле id_auto, а в id_spare пишется 0. И наоборот - для запчастей id_spare не пусто, а id_auto = 0. В этом случае получить объявления по определенному разделу очень просто - JOIN по нужном идентификатору. Сложности будут, если надо получить одновременно объявления из разных разделов. Но такая ситуация маловероятная, поэтому можно ею пренебречь.

Неактивен

 

#19 25.06.2009 16:09:37

zales
Участник
Зарегистрирован: 21.06.2009
Сообщений: 16

Re: Выбор оптимальной структуры для хранения списка объявлений (Partitioning)

а как же избыточность и нормальные формы? (или вы о моей идее хранить все объявления в одном месте) Может все-таки лучше несколько таблиц для объявлений: одну для авто, вторую для запчастей, третью для дисков, четвертую для колес. Тогда и поиск объявлений будет вестись по таблицам меньших размеров и ваше предложение "разделяй и властвуй" работает. smile

Неактивен

 

#20 25.06.2009 16:13:56

zales
Участник
Зарегистрирован: 21.06.2009
Сообщений: 16

Re: Выбор оптимальной структуры для хранения списка объявлений (Partitioning)

имеет ли смысл проводить оптимизацию по типам? (INT -> MEDIUMINT, SMALLINT, VARCHAR -> CHAR [MyISAM]) и т.д.

Неактивен

 

#21 25.06.2009 18:45:46

zales
Участник
Зарегистрирован: 21.06.2009
Сообщений: 16

Re: Выбор оптимальной структуры для хранения списка объявлений (Partitioning)

to Magz:
>> Таблица Adverts - данные об объявлении: кто подал, когда. Выделил отдельно от Autos (помимо более точного соответствия предметной области), так как сортировать наверняка придется по дате выдачи. Если эту дату "запихнуть" в Autos, то будут пробмы с индексами. К тому же, мы делаем независимым текущее состояние рынка (пул всех объявлений) и историю рынка (пул всех автомобилей). Это нам позволит строить аналитику по изменению цен, отследить путь машины (например, одну и ту же машину могут продавать несколько раз), оценивать машины путем сравнения.

Здесь связь между таблицами будет "один-к-одному", т.к. пользователь при подаче объявлений не может выбирать автомобиль из оставленных ранее. Они могут быть абсолютно идентичны по параметрам и даже быть одним автомобилем, но продаваться в разное время разными людьми. Конечно, логично было бы разделить сущности "машины" и "объявления". Может тогда лучше сделать структуру "звезда" вида:

ОБЪЯВЛЕНИЕ (кто, когда, доп.инфо)
--СВЯЗЬ--АВТОМОБИЛИ (параметры для этого автомобиля)--СВЯЗЬ--ОПЦИИ
--СВЯЗЬ--ЗАПЧАСТИ (параметры для этой запчасти)
--СВЯЗЬ--ДИСКИ
--СВЯЗЬ--ШИНЫ

Если бы объявление подавалось по VIN-коду, то тогда можно было бы говорить о соответствии "один-ко-многим".

Неактивен

 

#22 25.06.2009 23:34:13

zales
Участник
Зарегистрирован: 21.06.2009
Сообщений: 16

Re: Выбор оптимальной структуры для хранения списка объявлений (Partitioning)

to Magz: Вот последняя версия схемы (без запчастей, ...). Меня только смущают связи "один-к-одному", но как иначе это выразить я не знаю.

Смысл таков. Пользователь может быть как обычный (private), так и организация (autohouse). Объявление может быть об автомобиле (car), так и о запчастях (spare) и о дисках (drive).


Прикрепленные файлы:
Attachment Icon models.3.0.1.png, Размер: 22,102 байт, Скачано: 779

Неактивен

 

#23 29.06.2009 14:59:16

Magz
Гуру
Откуда: Москва
Зарегистрирован: 18.09.2007
Сообщений: 112

Re: Выбор оптимальной структуры для хранения списка объявлений (Partitioning)

zales, извините, сейчас полный загруз с работой, отпишусь сегодня-завтра.

Неактивен

 

#24 30.06.2009 10:27:15

zales
Участник
Зарегистрирован: 21.06.2009
Сообщений: 16

Re: Выбор оптимальной структуры для хранения списка объявлений (Partitioning)

smile ничего, все в порядке. Я пока новые вопросы ищу smile

Неактивен

 

Board footer

Работает на PunBB
© Copyright 2002–2008 Rickard Andersson