Forum |  HardWare.fr | News | Articles | PC | S'identifier | S'inscrire | Shop Recherche
2975 connectés 

 


 Mot :   Pseudo :  
 
 Page :   1  2
Page Suivante
Auteur Sujet :

Polymorphisme dans base de donnée?

n°1874617
esox_ch
Posté le 18-04-2009 à 11:03:53  profilanswer
 

Reprise du message précédent :
Bonjour,

 

Je pense que finalement je vais utiliser un modèle supporté par Rails qu'ils appellent "polymorphic associations". En gros le principe est que rails crée 2 champs "resource_type" et "resource_id" dans la classe mère (ici device) et utilise une FK sur ces champs pour linker les petits.
Voilà le SQL généré par Rails pour la création de table

 
Code :
  1. CREATE TABLE `screens` (`id` int(11) DEFAULT NULL AUTO_INCREMENT PRIMARY KEY, `model` varchar(255), `serial` varchar(255), `dvi` tinyint(1), `remarks` text, `created_at` datetime, `updated_at` datetime) ENGINE=InnoDB
  2. CREATE UNIQUE INDEX `index_screens_on_serial` ON `screens` (`serial`)
  3.  
  4. CREATE TABLE `scanners` (`id` int(11) DEFAULT NULL AUTO_INCREMENT PRIMARY KEY, `model` varchar(255), `serial` varchar(255), `remarks` text, `created_at` datetime, `updated_at` datetime) ENGINE=InnoDB
  5. CREATE UNIQUE INDEX `index_scanners_on_serial` ON `scanners` (`serial`)
  6.  
  7. CREATE TABLE `printers` (`id` int(11) DEFAULT NULL AUTO_INCREMENT PRIMARY KEY, `model` varchar(255), `color` tinyint(1), `ip` varchar(255), `hostname` varchar(255), `serial` varchar(255), `remarks` text, `created_at` datetime, `updated_at` datetime) ENGINE=InnoDB
  8. CREATE UNIQUE INDEX `index_printers_on_serial` ON `printers` (`serial`)
  9.  
  10. CREATE TABLE `desktops` (`id` int(11) DEFAULT NULL AUTO_INCREMENT PRIMARY KEY, `model` varchar(255), `serial` varchar(255), `os_id` int(11), `cpu` varchar(255), `ram` varchar(255), `graphic_card` varchar(255), `extensions` varchar(255), `hdd` varchar(255), `motherboard` varchar(255), `mac_addr` varchar(255), `ip` varchar(255), `hostname` varchar(255), `remarks` text, `created_at` datetime, `updated_at` datetime) ENGINE=InnoDB
  11. CREATE UNIQUE INDEX `index_desktops_on_serial` ON `desktops` (`serial`)
  12.  
  13. CREATE TABLE `devices` (`id` int(11) DEFAULT NULL AUTO_INCREMENT PRIMARY KEY, `workstation_id` int(11), `resource_id` int(11), `resource_type` varchar(255), `created_at` datetime, `updated_at` datetime) ENGINE=InnoDB
  14. CREATE INDEX `index_devices_on_workstation_id` ON `devices` (`workstation_id`)
  15.  
  16. CREATE TABLE `workstations` (`id` int(11) DEFAULT NULL AUTO_INCREMENT PRIMARY KEY, `name` varchar(255), `created_at` datetime, `updated_at` datetime) ENGINE=InnoDB
  17. CREATE UNIQUE INDEX `index_workstations_on_name` ON `workstations` (`name`)
 

J'ai peuplé la base de donnée d'un volume représentatif de ce qu'on risque d'avoir normalement. 500 Workstations, 1000 écrans, 100 scanners & imprimantes

 

J'ai effectué 2 requêtes qui me semble être particulièrement exigeantes en termes de resources.
La 1ère revient à demander la liste de l'équipement connecté à une workstation à la manière "Rails"

 
Code :
  1. >> ActiveRecord::Base.logger.silence do
  2. ?>    elapsed_time = Benchmark.realtime do
  3. ?>       Workstation.find_by_name("DZDHAY2" ).devices.each do |device|
  4. ?>          p device.resource.class
  5. ?>       end
  6. ?>    end
  7. >> end
  8.  
  9. Screen(id: integer, model: string, serial: string, dvi: boolean, remarks: text, created_at: datetime, updated_at: datetime)
  10. Screen(id: integer, model: string, serial: string, dvi: boolean, remarks: text, created_at: datetime, updated_at: datetime)
  11. Desktop(id: integer, model: string, serial: string, os_id: integer, cpu: string, ram: string, graphic_card: string, extensions: string, hdd: string, motherboard: string, mac_addr: string, ip: string, hostname: string, remarks: text, created_at: datetime, updated_at: datetime)
  12. => 0.00327801704406738


Donc 3.2 ms  => à priori ça devrait pas poser de soucis

 

Sans surprises ça se traduit en 1 select / table fille + quelques "SHOW TABLES" dont je ne connais pas la raison. Là je suis plus surpris c'est qu'il ne fait pas de jointure entre workstations et devices. Mais la traite "en interne", ce qui lui fait probablement perdre du temps :heink:
(Remarque : Les logs ci-dessous ont été obtenus en relançant la requête sans le logger.silence et Beanchmark.realtime

 
Code :
  1. Workstation LOAD (0.1ms)   SELECT * FROM `workstations` WHERE (`workstations`.`name` = 'DZDHAY2') LIMIT 1
  2.  Device LOAD (0.1ms)   SELECT * FROM `devices` WHERE (`devices`.workstation_id = 12)
  3.  Screen LOAD (0.0ms)   SELECT * FROM `screens` WHERE (`screens`.`id` = 792)
  4.  SQL (0.2ms)   SHOW TABLES
  5.  Screen LOAD (0.1ms)   SELECT * FROM `screens` WHERE (`screens`.`id` = 834)
  6.  SQL (0.1ms)   SHOW TABLES
  7.  Desktop LOAD (0.1ms)   SELECT * FROM `desktops` WHERE (`desktops`.`id` = 489)
  8.  SQL (0.2ms)   SHOW TABLES
 


La deuxième requête consiste à chercher quel à quelle Workstation est connecté un device donné (un écran dont le connais le serial pour mon exemple)

Code :
  1. ?> ActiveRecord::Base.logger.silence do
  2. ?>  elapsed_time = Benchmark.realtime do
  3. ?> p Screen.find_by_serial("692AVJXZ" ).device.workstation.name
  4. >> end
  5. >> end
  6. "2VD7VJ6"
  7. => 0.0013880729675293


Niveau simplicité du code c'est dur de faire beaucoup mieux je pense. Là encore 1 ms => ça devrait jouer..

 

Et la requête qui va avec ( plus de show table là par contre)

Code :
  1. Screen LOAD (0.1ms)   SELECT * FROM `screens` WHERE (`screens`.`serial` = '692AVJXZ') LIMIT 1
  2.  Device LOAD (0.0ms)   SELECT * FROM `devices` WHERE (`devices`.resource_id = 65 AND `devices`.resource_type = 'Screen') LIMIT 1
  3.  Workstation LOAD (0.0ms)   SELECT * FROM `workstations` WHERE (`workstations`.`id` = 324)
 

Même constat qu'avant, il semble ne pas faire de jointures entre les différentes tables...

 

Je précise que le script que j'ai utilisé pour peupler la base de donnée a généré des données "cohérentes" avec ce qu'il y aura dans ces champs ( = des string random de taille comparable à celles qui seront entrées)

 

Selon moi ça devrait jouer, vous voyez des soucis ?
Niveau maintenance, effectivement ce ne sera pas totalement indolore, mais c'est assez simplifié par les scripts de migration & generateurs de Rails, donc ça me va.

 

Merci à tous


Message édité par esox_ch le 18-04-2009 à 11:14:40

---------------
Si la vérité est découverte par quelqu'un d'autre,elle perd toujours un peu d'attrait
mood
Publicité
Posté le 18-04-2009 à 11:03:53  profilanswer
 

n°1875432
esox_ch
Posté le 20-04-2009 à 16:59:42  profilanswer
 

Ho j'me suis donné tout ce mal pour bien exprimer mes tests et ça interesse personne :lol:


---------------
Si la vérité est découverte par quelqu'un d'autre,elle perd toujours un peu d'attrait
n°1875483
LeRiton
Posté le 20-04-2009 à 18:10:20  profilanswer
 

Si, moi, mais j'ai pas réagi parce que je ne connaissais pas cette implé et que du même coup, ça sent le refactoring de mon côté :D

n°1877344
robbyone
Non pas !
Posté le 24-04-2009 à 13:23:25  profilanswer
 

Niveau performance, la méthode est de placer les données dans des tables, les jointures dans d'autres et d'indexer le tout. Les recherches se font sur les index et non sur les données : plus rapide.
 
Et ça a l'avantage de rester générique : pour ajouter un nouveau matériel, tu ajoutes une ligne dans la table matos (wkst, screen, ...) et sa configuration dans la table config (model, serial, ...)
 
Autre avantage, c'est de pouvoir ainsi avoir un historique des changements de configuration en datant chaque association.
 
C'est un peu ce que te propose Rails avec son Rails "polymorphic associations" mais il n'est pas complêtement générique : les devices sont encore des tables en dur.
 
Bon courage.

n°1879491
igarimasho
Posté le 29-04-2009 à 19:47:58  profilanswer
 

Quand les objects sont sauvés dans la BDD, comment fait-on un :joins ou :include avec la solution du polymorphisme?

n°1879921
esox_ch
Posté le 30-04-2009 à 20:02:58  profilanswer
 

Pas compris la question


---------------
Si la vérité est découverte par quelqu'un d'autre,elle perd toujours un peu d'attrait
mood
Publicité
Posté le   profilanswer
 

 Page :   1  2
Page Suivante

Aller à :
Ajouter une réponse
 

Sujets relatifs
SQL Server Reporting Services - Ecrire dans une base de données[BATCH/Windows] Changer valeur d'une chaine dans la base de registre
Question de base pour débuterj n arrive pas à créer une connexion java vers base de données mysql
API en PHP4 qui crée un fichier XML respectant un DTD donnée[PHP 5] base de données mysql : commande 'UPDATE' ?
classes et base de données =/imprimer un état en delphi 5 avec base access et ADOTable
Comment remplir une base avec un fichier texte?Problème de structure de base de donnée
Plus de sujets relatifs à : Polymorphisme dans base de donnée?


Copyright © 1997-2022 Hardware.fr SARL (Signaler un contenu illicite / Données personnelles) / Groupe LDLC / Shop HFR