2012-11-28 3 views
0

J'essaie d'optimiser une vue dans MySQL. La vue prend 0-5 enregistrements d'une table et les transforme en 1 enregistrement. La vue fonctionne, mais ralentit lorsque le nombre d'enregistrements dans la table property_log augmente.Optimiser la vue mysql qui fusionne plusieurs enregistrements en un seul enregistrement

Par exemple, les données qui ressemble à ceci:

mysql> select * from property_log where event_id = 1144882; 
+----------+--------------+------------------------------+ 
| event_id | log_key  | log_value     | 
+----------+--------------+------------------------------+ 
| 1144882 | userId  | 1000       | 
| 1144882 | licenseId | 3       | 
| 1144882 | messageTypeId| 7       | 
| 1144882 | message  | Sample message    | 
| 1144882 | op   | tracking      | 
+----------+--------------+------------------------------+ 

transformé en 1 gets enregistrement:

mysql> select * from view_logged_property where id = 1144882 
+---------+--------+-----------+---------------+-------------------+ 
| ID  | UserID | LicenseID | MessageTypeID | Message   | 
+---------+--------+-----------+---------------+-------------------+ 
| 1144882 | 1000 | 3   | 7    | Sample message | 
+---------+--------+-----------+---------------+-------------------+ 

Edit: Note importante - Pas tous les 5 enregistrements seront présents tout le temps. Par exemple, les données pourraient aussi regarder comme ceci:

mysql> select * from property_log where event_id = 1144882; 
+----------+--------------+------------------------------+ 
| event_id | log_key  | log_value     | 
+----------+--------------+------------------------------+ 
| 1144882 | userId  | 1000       | 
| 1144882 | messageTypeId| 7       | 
| 1144882 | message  | Sample message    | 
| 1144882 | op   | tracking      | 
+----------+--------------+------------------------------+ 

La vue que je suis actuellement en utilisant pour ce faire est la suivante:

DROP VIEW IF EXISTS view_logged_property; 
CREATE VIEW view_logged_property as (
    SELECT 
    p.event_id as ID, 
    (select log_value from property_log where log_key = "userId" and event_id = p.event_id) as UserID, 
    (select log_value from property_log where log_key = "licenseId" and event_id = p.event_id) as LicenseID, 
    (select log_value from property_log where log_key = "messageTypeId" and event_id = p.event_id) as MessageTypeID, 
    (select log_value from property_log where log_key = "message" and event_id = p.event_id) as Message 
    FROM 
    logging_event p 
    WHERE 
    p.event_id in (select event_id from property_log where log_key = "op" and log_value = "tracking") 
); 

Quelle est la meilleure façon d'écrire ce point de vue il » fonctionnera-t-il bien même si le nombre d'enregistrements dans la table "property_log" augmente?

Répondre

1

J'utiliseraient join s dans ce cas.

Modifié après commentaire left join s devrait résoudre le problème.

DROP VIEW IF EXISTS view_logged_property; 
CREATE VIEW view_logged_property as (
    select 
     p1.event_id as ID, 
     p5.log_value as UserID, 
     p2.log_value as LicenseID, 
     p3.log_value as MessageTypeID, 
     p4.log_value as Message 
    from property_log p1 
    left join property_log p5 on p1.event_id = p5.event_id and p5.log_key = 'userId' 
    left join property_log p2 on p1.event_id = p2.event_id and p2.log_key = 'licenseId' 
    left join property_log p3 on p1.event_id = p3.event_id and p3.log_key = 'messageTypeId' 
    left join property_log p4 on p1.event_id = p4.event_id and p4.log_key = 'message' 
    where p1.log_key = 'op' and p1.log_value = 'tracking' 
); 

Pourriez-vous tester il sur vos données?

Index sur la paire event_id, log_key peut être nécessaire, STH comme ci-dessous:

create index event_key_idx on property_log(event_id, log_key); 

SQL Fiddle example

+0

Hey! J'ai essayé ça et ça ne m'a pas donné de données ... mais c'est parce que je n'avais pas réalisé que tous les disques ne seraient pas présents tout le temps (parfois il n'y aura que 4 enregistrements, par exemple). J'ai ajouté une clarification à la question! –

+0

@BradParks donc au lieu de 'join' utiliser [' left join'] (http://en.wikipedia.org/wiki/Join_%28SQL%29#Left_outer_join), réponse corrigée. –

+0

Excellent! Merci beaucoup ... c'était infiniment plus rapide que mon approche ;-) –

1

essayer,

SELECT Event_ID, 
     MAX(CASE WHEN log_key = 'userID' THEN log_value ELSE NULL END) userID, 
     MAX(CASE WHEN log_key = 'licenseId ' THEN log_value ELSE NULL END) licenseId , 
     MAX(CASE WHEN log_key = 'messageTypeId' THEN log_value ELSE NULL END) messageTypeId, 
     MAX(CASE WHEN log_key = 'message' THEN log_value ELSE NULL END) message, 
     MAX(CASE WHEN log_key = 'op' THEN log_value ELSE NULL END) op 
FROM  property_log 
GROUP BY Event_ID 
Questions connexes