2010-06-02 2 views
2

Je stocke des informations très "sources de données" venant dans mon application. Ces sources de données peuvent être sous la forme d'un document (par exemple PDF, etc.), audio (par exemple MP3, etc.) ou vidéo (par exemple AVI, etc.). Supposons, par exemple, que je m'intéresse uniquement au nom de fichier de la source de données. Ainsi, j'ai le tableau suivant:Modélisation des données de l'entité avec des attributs

DataSource 
Id (PK) 
Filename 

Pour chaque source de données, j'ai également besoin de stocker certains de ses attributs. Exemple pour un PDF serait "nombre de pages." Exemple pour l'audio serait "débit binaire." Exemple pour la vidéo serait "durée". Chaque DataSource aura des exigences différentes pour les attributs qui doivent être stockés. Donc, j'ai modélisé « attribut source de données » de cette façon:

DataSourceAttribute 
Id (PK) 
DataSourceId (FK) 
Name 
Value 

Ainsi, j'avoir des dossiers comme ceux-ci:

DataSource->Id = 1 
DataSource->Filename = 'mydoc.pdf' 

DataSource->Id = 2 
DataSource->Filename = 'mysong.mp3' 

DataSource->Id = 3 
DataSource->Filename = 'myvideo.avi' 

DataSourceAttribute->Id = 1 
DataSourceAttribute->DataSourceId = 1 
DataSourceAttribute->Name = 'TotalPages' 
DataSourceAttribute->Value = '10' 

DataSourceAttribute->Id = 2 
DataSourceAttribute->DataSourceId = 2 
DataSourceAttribute->Name = 'BitRate' 
DataSourceAttribute->Value '16' 

DataSourceAttribute->Id = 3 
DataSourceAttribute->DataSourceId = 3 
DataSourceAttribute->Name = 'Duration' 
DataSourceAttribute->Value = '1:32' 

Mon problème est que cela ne semble pas à l'échelle. Par exemple, dire que je dois interroger pour tous les documents PDF ainsi que Thier nombre total de pages:

Filename, TotalPages 
'mydoc.pdf', '10' 
'myotherdoc.pdf', '23' 
... 

Le nécessaire pour produire les JOIN sont le résultat ci-dessus sont tout simplement trop coûteux. Comment dois-je résoudre ce problème?

Répondre

0

Mise à l'échelle est l'un des problèmes les plus courants avec EAV (Entité-attribute-value) des structures de données. En bref, vous devez demander les métadonnées (c'est-à-dire localiser les attributs) pour accéder aux données. Cependant, voici une requête que vous pouvez utiliser pour obtenir les données que vous voulez:

Select DataSourceId 
    , Min(Case When Name = 'TotalPages' Then Value End) As TotalPages 
    , Min(Case When Name = 'BitRate' Then Value End) As BitRate 
    , Min(Case When Name = 'Duration' Then Vlaue End) As Duration 
From DataSourceAttribute 
Group By DataSourceId 

Afin d'améliorer les performances, vous voulez un index sur DataSourceID et peut-être aussi bien Name. Pour obtenir les résultats que vous avez publiés, vous feriez:

Select DataSource.FileName 
    , Min(Case When DataSourceAttribute.Name = 'TotalPages' Then Value End) As TotalPages 
    , Min(Case When DataSourceAttribute.Name = 'BitRate' Then Value End) As BitRate 
    , Min(Case When DataSourceAttribute.Name = 'Duration' Then Vlaue End) As Duration 
From DataSourceAttribute 
    Join DataSource 
     On DataSource.Id = DataSourceAttribute.DataSourceId 
Group By DataSource.FileName 
0

On dirait que vous voulez quelque chose de plus losse qu'un db relationnel typique. On dirait un bon candidat pour quelque chose comme Lucene ou MongoDB. Lucene est un moteur d'index qui permet de stocker et d'indexer tout type de document. MongoDB est au milieu entre le SGBDR et le stockage de document de forme libre. JSON sous une forme ou une autre (MongoDB est un bon exemple) devrait s'intégrer bien.

+0

Je ne suis pas sûr si je suis prêt à introduire une autre technologie dans l'application. En ce moment, je veux essayer de résoudre cela via une modélisation de données appropriée. – StackOverflowNewbie

0

Cela pourrait fonctionner, mais définir trop coûteux ...

select 
datasource.id, 
d1.id as d1id, 
d1.value as d1filename, 
d2.id as d2id, 
d2.value as d2totalpages 

from datasource 
inner join datasourceattribute d1 
on datasource.id = d1.datasourceid and d1.name = 'filename' 
inner join datasourceattribute d2 
on datasource.id = d2.datasourceid and d2.name = 'totalpages' 
having d1filename like '%pdf' 
+0

@Zak: Ma requête était fondamentalement la même que la vôtre. J'ai couru 388 requêtes, qui ont pris 255.7976 secondes à exécuter. C'est plus de 4 minutes pour un si petit nombre de disques, non? – StackOverflowNewbie

+0

À quoi ressemblent vos index de table? – Zak

+0

aussi, préfixez cette requête avec "explain" puis exécutez-la dans votre ligne de commande, puis publiez les résultats ... – Zak

Questions connexes