web-dev-qa-db-fra.com

Les tables de jonction sont-elles une bonne pratique?

Disons que j'ai une grande table qui contient les informations de l'utilisateur et une autre table qui contient plusieurs emplacements. Ensuite, j'utilise une autre table contenant le user_id et le location_id.

Afin de récupérer les données, je dois utiliser la requête Left Join. Cela ne rend-il pas l'ensemble du processus plus long à récupérer plutôt que de tout avoir dans une seule table? Par exemple, je pourrais avoir l'emplacement sous forme de texte sur la même table.

EDIT: Voici un exemple.

CREATE TABLE  `user` (
`id` int(11) NOT NULL,
  `name` varchar(45) DEFAULT NULL,
  `gender` enum('M','F') DEFAULT NULL
);

CREATE TABLE `user_location` (
  `user_id` int(11) NOT NULL,
  `location_id` int(11) NOT NULL
);

CREATE TABLE `location` (
`id` int(11) NOT NULL,
  `location` varchar(45),
  `parent_id` varchar(45) 
);

Remarque: Veuillez supposer que tous les champs associés sont correctement indexés entre eux.

Edit: J'ai actuellement une grande base de données avec des utilisateurs qui récupèrent leur emplacement via une table de jonction comme décrit ci-dessus. On m'a demandé d'optimiser la base de données car les résultats de recherche sont lents. J'ai ajouté memcache et il s'est amélioré de manière significative, mais maintenant je me pose des questions sur les jointures gauches.

Par exemple, la requête actuelle est quelque chose comme ça:

SELECT * FROM users 
LEFT JOIN user_location 
ON user_location.user_id = user.id 
LEFT JOIN location
ON location.id = user_location.location_id;

Et c'est juste pour obtenir l'emplacement. Ils ont plusieurs autres champs qui sont récupérés via les jonctions et ils sont tous nécessaires pour afficher le profil d'un utilisateur. Nous avons des numéros de téléphone, des adresses, des mots de passe, D.O.B et bien d'autres dans des tableaux différents.

Pour que je puisse créer une page pour le profil utilisateur, je dois envoyer une grande requête au serveur. Maintenant, après la première fois, il est mis en cache et ça va. Mais je me demandais juste pourquoi quelqu'un construirait sa base de données comme ça?

7
Marios Frixou

Si vous mettez tout dans une table, vous aurez une table plus grande et redondante.

Si toutes les tables sont correctement indexées, la solution à 3 tables sera rapide, car un petit nombre de lignes sera lu pour chaque requête.

9
Federico Razzoli

Les tables de jonction sont une pratique très standard dans la conception de bases de données relationnelles. Il est couvert dans la base de données 101. Si vous avez une relation plusieurs-à-plusieurs entre deux entités, la manière standard de les représenter est d'utiliser trois tables.

Deux des tables sont des tables d'entité, avec une clé primaire. Une table de jonction se trouve entre eux (logiquement) et contient deux clés étrangères, une qui référence chaque table d'entité. Souvent, ces deux clés étrangères seront les deux seules colonnes de la table de jonction.

Je ne comprends pas pourquoi quelqu'un demanderait si c'est une bonne pratique, à moins qu'il n'ait jamais couvert la base de données 101.

8
Walter Mitty

"Veuillez supposer que tous les champs associés sont correctement indexés entre eux." Non, je ne ferai pas ça. Je vois trop d'utilisateurs qui n'ont jamais entendu parler des index "composites", et encore moins comprendre leur importance.

En particulier, vous devriez avoir:

CREATE TABLE user_location(
    # No surrogate id for this table
    user_id     MEDIUMINT UNSIGNED NOT NULL,   -- For JOINing to one table
    location_id MEDIUMINT UNSIGNED NOT NULL,   -- For JOINing to the other table
    # Include other fields specific to the 'relation'
    PRIMARY KEY(user_id, location_id),            -- When starting with user
    INDEX      (location_id, user_id)             -- When starting with location
) ENGINE=InnoDB;

De plus les notes sont dans mon blog .

4
Rick James

Votre approche avec DB est erronée. Une table n'est pas un ensemble de champs pour contenir des données que vous gérez en ajoutant/supprimant des colonnes sans critère. La structure DB est le résultat d'une analyse. Cette partie de Db est née d'exigences spécifiques: un utilisateur vit dans un ou plusieurs emplacements. Au même endroit peut vivre un ou plusieurs utilisateurs. Un utilisateur est identifié par un nom et un sexe. Un emplacement est identifié par l'id. Sur la base de ces exigences, vous identifiez 2 entités: les utilisateurs et les emplacements. Étant donné que l'association entre ces entités est un nombre trop important, transformant le schéma conceptuel en ER, vous obtiendrez (de manière matématique) un tableau spécifique concernant les emplacements d'utilisateurs, composé (au moins) par deux clés étrangères pointant vers les deux entités. Étant donné que le nom ne peut pas être utilisé comme clé primaire (car les personnes peuvent avoir le même nom), vous utilisez un ID (probablement avec une incrémentation automatique).

1
Marcello Kad

Si vous avez un EAV il vous suffit de INSERT une valeur par défaut de location_id = 0 ou 1 et sa description serait Non défini ou Non défini dans votre table locations. Créez un déclencheur qui INSERT par défaut dans le tableau avec le user_id Et location_id.

Ainsi, vous n'avez pas besoin d'utiliser LEFT JOIN Et de faire la recherche lentement, juste un JOIN. Si l'utilisateur a le location_id= 0 ou 1 (ce que vous avez pris) va retourner le location_name Par défaut.

Par ailleurs, la syntaxe LEFT JOIN Dépendra de votre index. Si vous avez un index sur ces champs, je ne vois pas le problème si votre table users n'est pas grande (en supposant).

0
oNare