2017-10-18 13 views
0

J'ai une base de données de 100 000 noms dans les cimetières. Les cimetières nombre autour de 6000 .... Je voudrais revenir le nombre de noms dans chaque cimetière ..Comment faire un nombre efficace de lignes d'une autre table (join)

Si je fais une requête individuelle, il faut une milliseconde

SELECT COUNT(*) FROM tblnames 
    WHERE tblcemetery_ID = 2 

Ma requête réelle continue et et je finis par le tuer, donc je ne tue pas notre base de données. Quelqu'un peut-il me signaler une méthode plus efficace?

select tblcemetery.id, 
    (SELECT COUNT(*) FROM tblnames 
     WHERE tblcemetery_ID = tblcemetery.id) AS casualtyCount 
    from tblcemetery              
     ORDER BY 
    fldcemetery 
+1

Il est difficile de dire sans voir un expliquer, mais si je Je devais faire une supposition, je dirais pour m'assurer que les deux champs que vous utilisez pour rejoindre votre sous-requête sont indexés. – JNevill

+0

Oui, désolé, dans chaque cimetière –

Répondre

2

Vous pouvez reformuler votre requête à utiliser une jointure au lieu d'une sous-requête corrélative:

SELECT 
    t1.id, 
    COUNT(t2.tblcemetery_ID) AS casualtyCount 
FROM tblcemetery t1 
LEFT JOIN tblnames t2 
    ON t1.id = t2.tblcemetery_ID 
GROUP BY 
    t1.id 
ORDER BY 
    t1.id 

J'ai entendu dire que dans certaines bases de données, telles que Oracle, l'optimiseur est assez intelligent pour comprendre ce que J'ai écrit ci-dessus, et refactoriser votre requête sous le capot. Mais l'optimiseur de MySQL n'est peut-être pas assez intelligent pour le faire.

Un effet secondaire agréable de ce refactor est que nous voyons maintenant une opportunité d'améliorer encore les performances, en ajoutant des index aux colonnes de jointure. Je suppose que id est la clé primaire de tblcemetery, auquel cas il est déjà indexé. Mais vous pouvez ajouter un index tblcemetery_ID dans le tableau tblnames pour un coup de pouce possible de la performance:

CREATE INDEX cmtry_idx ON tblnames (tblcemetery_ID) 
+0

Cela implique que vous anticipez qu'il y a un cimetière avec personne enfoui dedans. – Strawberry

+0

@ Fraise Beaucoup de gens aux États-Unis utilisent des morgues et des cimetières comme escroqueries fiscales. Cela ne m'étonnerait pas qu'il y ait quelques cimetières qui ne contiennent pas de morts. –

+0

... ou cimetières pour animaux de compagnie je suppose. – Strawberry

0

Ou vous pourriez rechercher group byhere f.e. et faire quelque chose comme

SELECT tblcemetery_ID, sum(1) from tblnames group by tblscemetery_id 

Vous additionnez essentiellement jusqu'à 1 pour chaque nom entrée qui appartient à ce cimetière que vous n'êtes pas interessé dans les noms du tout, pas besoin de joindre à la table de détail de cimetière

Vous ne savez pas si sum(1) ou count(*) est mieux, les deux devraient fonctionner.

Youll ne se cemetaries qui ont ppl l'intérieur si

0

Il pourrait même se faire sans JOIN en utilisant une clause EXISTS comme celui-ci

SELECT id, COUNT(*) AS casualtyCount 
FROM tblcemetery 
WHERE EXISTS (SELECT 1 FROM tblnames WHERE tblcemetery_ID=id) 
GROUP BY id 
ORDER BY id