Есть таблица лайков likes (`post_id`, `user_id`).
Если я вместо неё сделаю поле в таблице posts posts(..., `likes` text).
Где likes будет списком ID юзеров "1,55,66,77,...", а постановка лайка будет SET likes = likes + 'user_id'.
Выиграю ли я в скорости по получению поста с лайками / удаление лайка / постановка лайка, по сравнению с отдельной таблицей связи, тем самым избежав массовых insert/delete?
я уже пробовал с помощью обычной структуры.
Но меня тимлид (это задание для собес) послал, потому что типа куча инсертов/делитов на постановку/снятие лайка от множества юзеров это плохо. Только для небольших проектов. Вот думаю, думаю, как по другому организовать лайки...
l4m3r, пошли этого тимлида туда где он это прочитал. Он ничего не знает про индексацию, денормаоизацию, безопасность и изоляцию сервисов. Тимлид это не DBA и не Архитектор
Иван Шумов, а если у стандартной таблицы likes(post_id, user_id) добавить поле state 0/1. То по идее, мы только первый раз будем использовать insert от юзера, дальше только update. Это, наверное, несколько ускорит чем delete и insert?
l4m3r, денормализация это хорошо. Почти всегда. В любой системе есть write и read годы, если уж говорить про системы где это действительно важно. Поэтому вопрос ни о чем на самом деле. В больших проектах эти проблемы решаются не структурой данных. И делаются вообще на на реляционных базах
Иван Шумов, Я это понимаю! Хранение в одном поле - бред. Признаю.
Просто было задание "Составить таблицу лайков к постам от юзеров и запросы на постановку/снятие. База MySQL". Мой ответ им:
create table `likes` (
`post_id` int,
`user_id` int,
foreign key (`post_id`) references `posts`(`id`) on delete cascade,
foreign key (`user_id`) references `users`(`id`) on delete cascade,
primary key (`post_id`, `user_id`)
) engine=InnoDB, default character set = utf8;
-- insert into`likes`(`post_id`, `user_id`) values (1, 1); постановка
-- delete from `likes` where `post_id` = 1 and `user_id` = 1; снятие
Ответ от них: "подумать что будет с таблицей лайков если будет куча insert/delete (и как сделать лучше)."
Вот и что теперь?
l4m3r, подумать про отсутствие индекса и партицирования. Никто не писал что ваше решение плохое - оно просто недостаточное. А ещё нет времени появления лайков
l4m3r, да, тут согласен, совсем забыл про индексы. А про партицирование это тонкая тема. Вообще не знаю где такие вопросы задают - по мне так это уже к DBA, на коего вы, наверное, не претендуете.
Как в профиле юзера посмотреть, какие записи он лайкнул?
У вас появилась популярная и вы используете мускул. Что произойдет при одновременной вставке одного поля?
А если помощью отдельной таблицы, то мне сказали (это задание для собес), что типа куча инсертов/делитов на постановку/снятие лайка от множества юзеров это плохо. Только для небольших проектов. Мол, предложи лучший вариант..
l4m3r, Дык юзеры не ставят лайки одномоментно. Если в классической промежуточной таблице каждый лайк - это один INSERT, то со строкой - это, как минимум, UPDATE + CONCAT, то есть данные надо будет извлечь, проделать какие-то манипуляции и записать обратно.
В случае удаления строка ещё хуже. А уж для поиска она вообще не подходит.
l4m3r, Промежуточной таблицей. Самый лучший вариант.
Напишите, например, запрос со строкой для получения всех постов, которые лайкал конкретный пользователь. А теперь попробуйте сделать так, чтобы он использовал индекс по полу `likes`. Заранее говорю, не получится. Запросы вида LIKE '%...' не индексируются вообще.
Rsa97, Дык проблема в том, что на решение промежуточной таблицей, пришёл ответ что на каждый лайк делать инсерт, а на каждое снятие лайка delete - плохо.
create table `likes` (
`post_id` int,
foreign key (`post_id`) references `posts`(`id`) on delete cascade,
foreign key (`user_id`) references `users`(`id`) on delete cascade,
primary key (`post_id`, `user_id`)
) engine=InnoDB, default character set = utf8;
А если помощью отдельной таблицы, то мне сказали (это задание для собес), что типа куча инсертов/делитов на постановку/снятие лайка от множества юзеров это плохо. Только для небольших проектов. Мол, предложи лучший вариант..
Количество апдейтов зависит от количества лайков
Вопрос в том куда они будут направлены
Если они будут направлены в одно поле - появляется куча ограничений и вместо СУБД следить за связями придется разработчику
Я могу предложить вам вариант отклонить данную контору, тк они не компетентны
l4m3r, когда кто-то просит вас сломать 3NF - смотрите ему в глаза и спрашивайте, чем он готов пожертвовать, ради чего, в каких местах код придется переусложнить
sim3x, `id` в данном случае не обязателен, достаточно сделать составной первичный ключ (`post_id`, `user_id`).
CREATE TABLE `like` (
`post_id` INT NOT NULL,
`user_id` INT NOT NULL,
FOREIGN KEY (`post_id`) REFERENCES `posts`(`id`) ON DELETE CASCADE,
FOREIGN KEY (`user_id`) REFERENCES `users`(`id`) ON DELETE CASCADE,
PRIMARY KEY (`post_id`, `user_id`),
INDEX ('user_id'),
)