esox_ch | 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 :
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 CREATE UNIQUE INDEX `index_screens_on_serial` ON `screens` (`serial`) 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 CREATE UNIQUE INDEX `index_scanners_on_serial` ON `scanners` (`serial`) 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 CREATE UNIQUE INDEX `index_printers_on_serial` ON `printers` (`serial`) 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 CREATE UNIQUE INDEX `index_desktops_on_serial` ON `desktops` (`serial`) 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 CREATE INDEX `index_devices_on_workstation_id` ON `devices` (`workstation_id`) CREATE TABLE `workstations` (`id` int(11) DEFAULT NULL AUTO_INCREMENT PRIMARY KEY, `name` varchar(255), `created_at` datetime, `updated_at` datetime) ENGINE=InnoDB 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 :
>> ActiveRecord::Base.logger.silence do ?> elapsed_time = Benchmark.realtime do ?> Workstation.find_by_name("DZDHAY2" ).devices.each do |device| ?> p device.resource.class ?> end ?> end >> end Screen(id: integer, model: string, serial: string, dvi: boolean, remarks: text, created_at: datetime, updated_at: datetime) Screen(id: integer, model: string, serial: string, dvi: boolean, remarks: text, created_at: datetime, updated_at: datetime) 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) => 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 (Remarque : Les logs ci-dessous ont été obtenus en relançant la requête sans le logger.silence et Beanchmark.realtime Code :
Workstation LOAD (0.1ms) SELECT * FROM `workstations` WHERE (`workstations`.`name` = 'DZDHAY2') LIMIT 1 Device LOAD (0.1ms) SELECT * FROM `devices` WHERE (`devices`.workstation_id = 12) Screen LOAD (0.0ms) SELECT * FROM `screens` WHERE (`screens`.`id` = 792) SQL (0.2ms) SHOW TABLES Screen LOAD (0.1ms) SELECT * FROM `screens` WHERE (`screens`.`id` = 834) SQL (0.1ms) SHOW TABLES Desktop LOAD (0.1ms) SELECT * FROM `desktops` WHERE (`desktops`.`id` = 489) 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 :
- ?> ActiveRecord::Base.logger.silence do
- ?> elapsed_time = Benchmark.realtime do
- ?> p Screen.find_by_serial("692AVJXZ" ).device.workstation.name
- >> end
- >> end
- "2VD7VJ6"
- => 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 :
Screen LOAD (0.1ms) SELECT * FROM `screens` WHERE (`screens`.`serial` = '692AVJXZ') LIMIT 1 Device LOAD (0.0ms) SELECT * FROM `devices` WHERE (`devices`.resource_id = 65 AND `devices`.resource_type = 'Screen') LIMIT 1 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
|