2010-04-15 6 views
1

J'ai deux entités A et B. Elles sont liées avec plusieurs à plusieurs relations. L'entité A peut être liée jusqu'à 100 entités B. L'entité B peut être liée jusqu'à 10000 entités A. J'ai besoin d'un moyen rapide de sélectionner par exemple 30 entités A, qui ont une relation avec des entités B spécifiées, filtrées et triées par différents attributs.Champ SET d'indexation

Voici comment je vois la solution idéale: je mets toutes les informations que je connais sur les entités A, y compris leurs relations avec les entités B en une seule ligne (Table spéciale avec champ SET) puis ajoutez tous les index nécessaires. Le problème est que vous ne pouvez pas utiliser l'index lors d'une requête par champ SET. Que devrais-je faire? Je peux remplacer la base de données par quelque chose de différent, si cela peut vous aider.

MISE À JOUR: Je suis désolé. On dirait que j'ai oublié de mentionner un détail important. J'ai besoin de trouver les entrées A qui ont des relations avec l'entrée B avec id = 1 et avec l'entrée B avec id = 2 en même temps. Donc, si vous utilisez rejoint je vais avoir quelque chose de similaire à:

SELECT a.id, COUNT (*) comme un cnt DE INNER JOIN ab = ON a.id ab.a_id OÙ ab.b_id IN (1, 2) GROUPE pAR ORDRE a.id pAR NULL ayant cnt = 2

ce qui me donne très mauvaise perfomance

Répondre

1

Pourquoi faites-vous tout simplement pas:

SELECT * 
FROM a 
WHERE a.id IN 
     (
     SELECT ab.a 
     FROM b 
     JOIN ab 
     ON  ab.b = b.id 
     WHERE b.id IN (1, 2, 3, 4) 
     ) 

et de créer un PRIMARY KEY au ab (b, a)?

Mise à jour:

Utilisez ceci:

SELECT * 
FROM a 
WHERE (
     SELECT COUNT(*) 
     FROM ab 
     WHERE ab.a = a.id 
       AND ab.b IN (1, 2, 3, 4) 
     ) = 4 
ORDER BY 
     ... 
LIMIT 30 

ou ceci:

SELECT a.* 
FROM (
     SELECT a 
     FROM ab 
     WHERE ab.b IN (1, 2, 3, 4) 
     GROUP BY 
       a 
     HAVING COUNT(*) = 4 
     ) q 
JOIN a 
ON  a.id = q.id 
ORDER BY 
     ... 
LIMIT 30 

Vous aurez besoin d'avoir un PRIMARY KEY sur ab (b, a) (dans cet ordre) pour que cela fonctionne rapide .

La requête la plus efficace dépend de la distribution de vos données.

+0

Je suis désolé. On dirait que j'ai oublié de mentionner un détail important. J'ai besoin de trouver les entrées A qui ont des relations avec l'entrée B avec id = 1 et avec l'entrée B avec id = 2 en même temps. Donc, si vous utilisez des jointures, je vais avoir quelque chose de similaire à: SELECT a.id, count (*) en tant que cnt FROM INNER JOIN ab sur a.id = ab.a_id OERE ab.b_id IN (1,2) GROUP BY a.id ORDER BY NULL ayant cnt = 2 Ce qui me donne une très mauvaise performance – Dienow

+0

Cela a encore une performance terrible. Pour certaines valeurs d'entrée, la requête prend jusqu'à 1 seconde à effectuer, ce qui est inacceptable dans mon cas. Le problème est que l'entité de b peut être connectée avec des milliers d'entités de a. C'est pourquoi la sous-requête doit traiter un trop grand nombre de lignes, ce qui donne de très mauvaises performances même si toutes les données nécessaires sont extraites de l'index (USING INDEX). – Dienow

+0

@Dienow: pourriez-vous publier la sortie de 'EXPLAIN SELECT ...' avec la sortie de 'SHOW CREATE TABLE a' et' SHOW CREATE TABLE b'? – Quassnoi