Дизайн базы данных: несколько таблиц по сравнению с одной таблицей

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

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

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

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

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

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

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

Ответ 1

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

Ответ 2

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

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

  • ID
  • название
  • Содержание
  • user_id (автор)
  • Дата
  • и т.д.

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

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

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

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

  • ID
  • название
  • каталог
  • 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

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

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

Ответ 3

Так что, если я не ошибаюсь, вы пытаетесь создать таблицу 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-запроса, приведенного выше, вы можете получить избранные сообщения, которым пользуется ID 6.

+-----+------------------+
| ID  |      Title       |
+-----+------------------+
| 935 | Hello, world!    |
+-----+------------------+