2009-04-09 13 views
1

Schéma EAV standard: une colonne pour ID d'entité, une pour ID d'attribut, une pour ID de valeur.Quel est le moyen le plus rapide d'interroger à partir d'une base de données EAV historique?

schéma historique EAV: Ajouter une colonne supplémentaire (s) pour les temps/date varie

Au moment de l'exécution, certaines lignes seront exclues. Il peut y avoir 0, 1 ou plusieurs lignes retournées par entité, par attribut. Nous voulons seulement la valeur la plus récente pour chaque attribut restant. Notre solution actuelle utilise la fonction SQL Server Rank() pour marquer chaque rang avec un rang, puis dans la clause where nous avons "et rank = 1".

Cependant, les performances ne sont pas satisfaisantes. Au cours de l'analyse, nous trouvons que l'attribution des rangs est assez rapide, cependant faire la clause where par rapport au rang nécessite un deuxième balayage des données, et conserve l'ensemble des données dans la RAM.

Quelle est la méthode la plus rapide pour classer les lignes d'attributs restantes et retourner uniquement les dernières?

+0

Suivez ces instructions pour publier plus d'informations sur votre question de requête lente: http://www.brentozar.com/archive/2009/03/getting-help-with-a-slow-query/ –

Répondre

1

L'idée générale serait d'extraire la dernière + clé en premier, puis de revenir en arrière pour obtenir une valeur qui ne fait pas partie de l'agrégat. Le fait que ce soit EAV n'a pas d'importance.

SELECT 
    * 
FROM 
    table t 
    JOIN 
    (SELECT MAX(dt) AS mdt, eID, aID FROM table GROUP BY eID, aID) mt 
        ON t.eID = mt.eID AND t.aID = mt.aID AND t.dt = mt.mdt 
WHERE 
    ... 
1

Bien que je pense que la réponse de GBN est probablement suffisante, je me demande si l'utilisation d'une clause OVER pour établir une date MAX par identifiant/attribut avec lequel pour réduire le SELECT dans une clause WHERE ne serait pas plus rapide qu'un RANG? Pas le temps de tester les performances, mais voici la requête:

select * 
from (
    select *, max(dt) over (partition by eID, aID) maxdt 
    from table 
) t 
where t.dt = t.maxdt and ... 

Bonne chance!

Questions connexes