Проектирование базы данных: несколько таблиц против одной таблицы - PullRequest
12 голосов
/ 26 января 2012

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

  1. Создайте таблицу для избранного пользователя для каждого типа объекта.
  2. Создать общую таблицу для всех типов объектов для всех пользователей.

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

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

Какая из двух стратегий будет более масштабируемой.

1-й влечет за собой несколько запросов к базе данных, а второй - влечет за собой большой столик.

Если это поможет, я использую MySql

Ответы [ 3 ]

8 голосов
/ 26 января 2012

Кажется, что вы уже знаете ответ, но помните, что системы, которые вы проектируете, легко изменяются, поскольку бизнес-модели всегда меняются со временем или в конечном итоге выходят из строя (это обобщение, но вы поняли).Следствием этого является то, что если вы сделаете жесткую модель, быструю или медленную, она жесткая, изменения будут сложнее, и конечный пользователь не увидит разницу, следовательно, изменение денег / счастья не будет достигнуто, если это не очень плохое изменение.Ваша проблема не техническая в том смысле, как запрос работает на движке, а скорее философская, легкие изменения в сравнении с кажущейся скоростью.Спросите себя, в чем преимущество наличия нормализованной базы данных?Подумайте о чистой архитектуре и дизайне, производительность является наименьшей проблемой в современном мире, поскольку обработка дешевле, а также хранение.Но дизайн дорогой.Нормализация была сделана для того, чтобы создавать системы, которые зависят не от решений последнего момента, а от структурированного процесса проектирования.Большие таблицы не имеют большого значения для MySql, но их важно поддерживать, модифицировать и расширять.Это не просто добавление еще одного столбца, речь идет о жесткой структуре самих данных.Со временем вы просто добавите столбцы, которые содержат индексы, и эти индексы будут указывать на маленькие таблицы.MySql будет пахать все эти данные в любом случае.Итак, я пойду к первому, много маленьких столов, много ко многим.

4 голосов
/ 26 января 2012

У меня есть этот дизайн на моем сайте.Мои модули: новости, статьи, видео, фотографии, загрузки, обзоры, тесты, опросы и т. Д. И т. Д. Все в отдельных таблицах.У меня есть таблица лайков, где пользователям могут нравиться или не нравиться пост (в вашем случае избранное).Запрос, чтобы получить их, не так уж и сложен.

Во-первых, большинство моих таблиц для модулей структурированы одинаково:

  • id
  • title
  • content
  • user_id (author)
  • date
  • и т. Д.

с некоторыми исключениями, которые иногдаЗаголовок называется вопрос или нет столбца контента.Это не вызывает каких-либо проблем.

Мои таблицы лайков настроены так:

  • id
  • page_id
  • module_id (какая таблица былаэто происходит из ... У меня есть таблица модулей, где у каждого модуля есть заголовок, связанный идентификатор, каталог и т. д.)
  • post_id (соответствует идентификатору таблицы модулей)
  • user_id (пользователь, которыйнравится или опубликовано)
  • статус (0 = нравится, 1 = не нравится)
  • дата (когда имело место / не понравилось)

Пример таблицы модулей:

  • id
  • title
  • directory
  • post_type

Пример

id      title              directory         post_type
 1       News                news               news
 2     Episode Guide       episodes            episode
 3       Albums           discography/albums    album

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

Запрос для получения всех лайков или избранных для конкретного пользователя:

$getlikes = mysql_query("SELECT DISTINCT post_id, module_id, page_id FROM likes WHERE user_id = $profile_id ORDER BY id DESC LIMIT $offset, $likes_limit", $conn);
$likes = mysql_num_rows($getlikes);

if($likes == "0"){
echo "<br><Center>$profile_username does not have any liked posts at this time.</center><BR>";
}
else {
echo "<table width='100%' cellspacing='0' cellpadding='5'>

<Tr><th>Post</th><th align='center'>Module</th><th align='center'>Page</th><tr>";

while ($rowlikes = mysql_fetch_assoc($getlikes)) {
   // echo data

$like_page_id = $rowlikes['page_id'];
$like_module_id = $rowlikes['module_id'];
$like_post_id = $rowlikes['post_id'];


// different modules have different fields for the "title", most are called title but quotes is called "content" and polls is called "questions"
if($like_module_id == "11"){
$field = "question";
}
elseif($like_module_id == "19"){
$field = "content";
}
else{
$field = "title";
}





// FUNCTIONS
PostURL($like_page_id, $like_module_id, $like_post_id);
ModTitle($like_module_id);
ModTable($like_module_id);
ModURL($like_page_id, $like_module_id);
fpgURL($like_page_id);


$getpostinfo = mysql_query("SELECT $field AS field FROM $mod_table WHERE id = $like_post_id", $conn);
$rowpostinfo = mysql_fetch_assoc($getpostinfo);
$like_post_title = $rowpostinfo['field'];

// Using my "tiny" function to shorten the title if the module is "Quotes"
if($like_module_id == "19"){
Tiny($like_post_title, "75");
$like_post_title = "\"$tiny\"";
}


if(!$like_post_title){
$like_post_title = "<i>Unknown</i>";
}
else {
$like_post_title = "<a href='$post_url'>$like_post_title</a>";
}

echo "<tr class='$altrow'>
<td>$like_post_title</td>
<td align='center'><a href='$mod_url'>$mod_title</a></td>
<td align='center'>$fpg_url</td>


</tr>";

$altrow = ($altrow == 'altrow')?'':'altrow';

} // end while

echo "<tr><Td align='center' colspan='3'>";

// FUNCTIONS - Pagination links
PaginationLinks("$cs_url/users/$profile_id", "likes");

echo "</td></tr></table>";

} // end else if no likes

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

У меня настроены функции «модуля», которые будут возвращать URL-адрес или заголовок предоставленного вами модуляидентификатор для этого.

0 голосов
/ 09 декабря 2018

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

Типы : типы ресурсов.

+----+---------+
| ID |  Name   |
+----+---------+
|  0 | blog    |
|  1 | post    |
|  2 | article |
|  3 | photo   |
|  4 | video   |
+----+---------+

Избранное : наиболееважная часть системы «Избранное», это своего рода карта отношений.

+--------+----------+--------------+
| UserID | TargetID | TargetTypeID |
+--------+----------+--------------+
|    941 |        1 |            0 |
|      6 |      935 |            1 |
|     26 |       51 |            4 |
|      7 |       87 |            2 |
+--------+----------+--------------+

Сообщения : в примере таблицы сообщений вы также можете иметь Blogs или Photos и Albums таблицы.

+-----+------------------+
| ID  |      Title       |
+-----+------------------+
|   0 | This is my post! |
|  51 | Oh, how are you? |
| 935 | Hello, world!    |
+-----+------------------+

Теперь SQL-запрос может выглядеть следующим образом (не проверено):

-- Get the posts
SELECT p.*
FROM Posts p
LEFT JOIN Favorites f 
-- Which are favorited by the user 6
ON f.UserID = 6 
-- Also get the type id of the `post`,
-- so we can specify the favorite type of the favorite items
AND f.TargetTypeID = (
    SELECT ID 
    FROM Types
    WHERE Name = 'post'
)
-- Make sure we only get the posts which are favorited by the user.
WHERE p.ID = f.TargetID

С помощью SQL-запроса выше вы можете получить избранные сообщения, которые были добавлены в избранноепо идентификатору пользователя 6.

+-----+------------------+
| ID  |      Title       |
+-----+------------------+
| 935 | Hello, world!    |
+-----+------------------+
Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...