【问题标题】:Optimize mysql view that merges multiple records into one record优化mysql视图将多条记录合并为一条记录
【发布时间】:2012-11-28 23:48:36
【问题描述】:

我正在尝试优化 MySql 中的视图。该视图从表中获取 0-5 条记录并将它们转换为 1 条记录。该视图有效,但随着 property_log 表中记录数的增加而变慢。

例如,如下所示的数据:

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                     |
+----------+--------------+------------------------------+

变成1条记录:

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

编辑:重要提示 - 并非所有 5 条记录都会一直存在。例如,数据也可能如下所示:

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                     |
+----------+--------------+------------------------------+

我目前用于执行此操作的视图如下:

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")
);

编写此视图的最佳方法是什么,即使“property_log”表中的记录数增加,它也能很好地执行?

【问题讨论】:

    标签: mysql sql optimization view


    【解决方案1】:

    在这种情况下我会使用joins。

    评论后更改left joins 应该可以解决问题。

    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'
    );
    

    你能在你的数据上测试它吗?

    可能需要对 event_id, log_key 的索引,如下所示:

     create index event_key_idx on property_log(event_id, log_key);
    

    SQL Fiddle example

    【讨论】:

    • 嘿!我试过这个,它没有给我任何数据......但那是因为我没有意识到并非所有记录都会一直存在(例如,有时只有 4 条记录)。我已对问题进行了澄清!
    • @BradParks 所以而不是join 使用left join,答案更正。
    • 太棒了!非常感谢...这比我的方法快得多;-)
    【解决方案2】:

    试试这个,

    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
    

    【讨论】:

      猜你喜欢
      • 2017-02-24
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 2021-04-14
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      相关资源
      最近更新 更多