10

Хочу написать свое веб-приложение. Раньше никогда не занимался проектированием БД. Прошу оценить и указать мои ошибки. Идея такая

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

введите сюда описание изображения

UDP Обновил

введите сюда описание изображения

MrGarison
  • 676
  • 1
    В таблицах friends, users_to_roles и им подобных собственный id записи не нужен, включайте оба значимых поля в parimary key и все. Заодно уникальность записи обеспечите, что бы user1 не мог быть другом user2 дважды. Картинки ... Я бы отдельно хранил и в базе пути или вообще только некий id по которому потом путь вычисляется. Так будет проще картинки разложить на несколько серверов и отдавать быстро ngix без использования базы – Mike Jan 22 '16 at 15:43
  • 1
    messages_to_photos - как фотография может прочитать ваше сообщение? Может все-таки комментарии? И не совсем ясно с вашими диалогами и сообщениями - как это работать должно? И зачем messages_to_photos, если можно сразу внести photo_id в messages Не совсем понятно зачем все эти таблицы нужны (возможно, из-за неудачных названий). Если dialog - это общение нескольких людей, то как определить кому принадлежит сообщение? Если это только один человек - то почему диалог? И почему бы тогда не внести user_id в dialogs? – BOPOH Jan 22 '16 at 15:46
  • 1
    "что бы user1 не мог быть другом user2 дважды" - user1, user2 и user2, user1 –  Jan 22 '16 at 15:46
  • 1
    @Igor, проверять-то можно только по первому полю, тогда такие записи будут нормально обрабатываться + отсутствие второй записи может означать, например, "подписку" (как в вк) + кластеризация так лучше отработает – BOPOH Jan 22 '16 at 15:48
  • 1
    @Igor user1, user2 и user2, user1 - это нормальная ситуация. Одной из записей может не быть, если только user1 добавил user2, но не на оборот. А вот допускать две записи user1, user2 и user1, user2 точно нельзя – Mike Jan 22 '16 at 15:49
  • @BOPOH если добавить photo_id в message то как быть если фото не будет в сообщении? или если будет много фотографий в одном сообщении? тож самое и в таблице dialogs. user_to_dialogs и messages_to_photos это связующие таблицы – MrGarison Jan 22 '16 at 15:56
  • 1
    @MrGarison, ну я и говорю - не совсем понятно что вы хотели сделать. Лучше бы еще словами описали как эти таблицы связаны. Если фотографию можно в сообщение добавить - тогда да, вносить это не надо. Мой комент относился к случаю, когда "сообщение" было комментом к фотографии. Если users_to_dialogs - это связующая таблица, то как определить кто сообщение написал? А если фотография не добавлена ни в один альбом - как определить какому пользователю она принадлежит? – BOPOH Jan 22 '16 at 16:02
  • 1
    в photos есть поле tag, а если еще отдельно таблица тегов - это разные данные, просто названы одинаково? или вы просто забыли удалить tag из photos? – BOPOH Jan 22 '16 at 16:07
  • @BOPOH tag хотел сначала хранить в таблице фото, потом решил сделать отдельную таблицу, забыл удалить. В таблицу message добавил user_id, чтоб было ясно кто написал сообщение. Если пользователь будет отправлять картинки в сообщениях, то будет создаваться какой-нибудь стаднартный альбом, где будут храниться картинки переданные в сообщениях. – MrGarison Jan 23 '16 at 21:35
  • 1
    Убедительная просьба не вносить изменения в суть вопроса, в данном случае суть это ошибки в конкретной структуре БД. Оставьте какую-то одну. Сейчас ответов ещё нет, но если бы они были, их авторы попали бы в неоднозначную ситуацию. –  Jun 22 '16 at 16:58

1 Answers1

1

Касательно того, где хранить фотографии, то однозначно на сервере! Выкиньте из головы даже теоретическую возможность пихать блобы в БД!

Я недавно переделывал класс загрузчика на gd и систему хранения файлов (картинок), и остановился на таком варианте.

В СУБД (MariaDB) я храню тип файла (раширение) в поле ENUM. Если связь один 1 к 1, то это просто поле img ENUM('jpg','png','gif'),. Если связь 1 ко многим, то таблица.

CREATE TABLE `tbl_goods_img`
(
    `gid` BIGINT UNSIGNED NOT NULL,
    `order` TINYINT UNSIGNED NOT NULL,
    `img` ENUM('jpg','png','gif') NOT NULL,
    PRIMARY KEY(`gid`,`order`)
)
ENGINE=InnoDB CHARACTER SET utf8 COLLATE utf8_general_ci;

Основная моя идея в том, что название файла у меня состоит из id-шников, разделителя и точкой с расширением. Например 13.jpg или 6-2.png, где 13 - это, id соответствующего поля поля в этой таблице, или 6 - это gid, а 2 - это order соответствующего поля ранее приведенной таблицы.

В таком случае наличие img отличного от NULL нам указывает на существование файла и его тип, а имя файла вычисляется динамически и оно предсказуемо.

SELECT *,CONCAT(`id`,'.',`img`)`img` FROM `tbl_user`;
SELECT `gid`,`order`,CONCAT(`gid`,'-',`order`,'.',`img`)`img` FROM `tbl_goods_img`;

И подобные запросы сразу нам выдают полное имя картинки в поле img, причём если оно отсутствует, (img IS NULL) то CONCAT, и соответственно, img вернёт тоже NULL.

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