mysql - 优化查看大量数据的 MySQL 查询

标签 mysql sql database

所以我有一个错误日志需要分析。该日志是一个巨大的文件,约有 250 万行。

在该错误日志中,有一些字段称为:

EVENT_ATTRIBUTE 显示收集该事件的设备的名称 信息。

EVENT_SEVERITY 显示从 1 到 5 的数字。在此列中,我需要查找 1、2、4 和 5 的数量。

这是我使用的表格屏幕截图的链接:

/image/Yk4dq.png

我基本上需要获取 event_attribute 并计算 event_severity 的数量并将它们放在单独的列中。因此,与每个 event_attribute 相关的 1 和 2 的数量将被拆分,这样我就可以计算每个传感器(event_attribute)拾取的每种类型的错误量。

目前这是我的代码:

    SELECT LEFT(EVENT_ATTRIBUTE, LOCATE('(', EVENT_ATTRIBUTE, 1)-1) AS 
    SensorName, 
       SUM(EVENT_SEVERITY = 1) CODE_1,
       SUM(EVENT_SEVERITY = 2) CODE_2,
       SUM(EVENT_SEVERITY = 4) ERROR_4,
       SUM(EVENT_SEVERITY = 5) ERROR_5
    FROM taddmapp.disc_event
    WHERE EVENT_SEVERITY = 5 OR EVENT_SEVERITY = 4 OR EVENT_SEVERITY = 2 OR 
      EVENT_SEVERITY = 1 
    GROUP BY LEFT(EVENT_ATTRIBUTE, LOCATE('(', EVENT_ATTRIBUTE, 1)-1);

代码的LEFT(EVENT_ATTRIBUTE, LOCATE('(', EVENT_ATTRIBUTE, 1)-1)部分只是删除正在使用的传感器的IP地址,另一个选择总和的数量状态代码。代码运行良好,为我带来了我需要的结果,但唯一的问题是它花费的时间太长。前几天我运行了它,执行这个查询花了一个多小时。我想知道是否有无论如何我都可以优化这个查询。我不太擅长 SQL,所以我需要帮助优化。

感谢您的宝贵时间!

最佳答案

如果无法向表中添加列,那么我们可以尝试重写查询以有效利用以 EVENT_ATTRIBUTE 作为前导列的索引。使用这样的索引:

... ON taddmapp.disc_event (EVENT_ATTRIBUTE,EVENT_SEVERITY)

我们尝试让 MySQL 使用该索引并避免“使用文件排序”操作来满足内部查询中的 GROUP BY。

SELECT SUBSTRING_INDEX(t.EVENT_ATTRIBUTE,'(',1) AS 
SensorName
     , SUM(t.CODE_1) AS CODE_1
     , SUM(t.CODE_2) AS CODE_2
     , SUM(t.ERROR_4) AS ERROR_4
     , SUM(t.ERROR_5) AS ERROR_5
  FROM ( SELECT e.EVENT_ATTRIBUTE
              , SUM(e.EVENT_SEVERITY = 1) AS CODE_1
              , SUM(e.EVENT_SEVERITY = 2) AS CODE_2
              , SUM(e.EVENT_SEVERITY = 4) AS ERROR_4
              , SUM(e.EVENT_SEVERITY = 5) AS ERROR_5
           FROM taddmapp.disc_event e
          WHERE e.EVENT_SEVERITY IN (1,2,4,5)
          GROUP BY e.EVENT_ATTRIBUTE
       ) t
 GROUP
    BY SUBSTRING_INDEX(t.EVENT_ATTRIBUTE,'(',1)

注意:外部查询上的 GROUP BY 仍然需要“使用文件排序”操作,但这里的目标是让外部查询对更小的行集进行操作(假设内联 View 中的 GROUP BY将这 250 万行折叠成一个大小更合理的集合。)


如果我们只有一个裸柱,例如EVENT_ATTRIBUTE_PREFIX 仅填充了我们感兴趣的 EVENT_ATTRIBUTE 的前导部分,因此我们可以避免使用内联 View 。假设我们有该列,并且它是索引中的前导列,例如

... ON taddmapp.disc_event (EVENT_ATTRIBUTE_PREFIX,EVENT_SEVERITY)

然后 MySQL 可以利用该索引来满足 GROUP BY 操作,而不需要“使用文件排序”操作,查询如下:

SELECT e.EVENT_ATTRIBUTE_PREFIX  AS SensorName
     , SUM(e.EVENT_SEVERITY = 1) AS CODE_1
     , SUM(e.EVENT_SEVERITY = 2) AS CODE_2
     , SUM(e.EVENT_SEVERITY = 4) AS ERROR_4
     , SUM(e.EVENT_SEVERITY = 5) AS ERROR_5
  FROM taddmapp.disc_event e
 WHERE e.EVENT_SEVERITY IN (1,2,4,5)
 GROUP BY e.EVENT_ATTRIBUTE_PREFIX

关于mysql - 优化查看大量数据的 MySQL 查询,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/44685273/

相关文章:

php - 使用 PDO::prepare 创建一个在其 create 语句中有问号的函数?

mysql - Cron 作业制作日期数据库条目

mysql - 如何为每个企业选择最近的三个评论?

database - 谁能说存储过程的优缺点和 Java 存储过程的优缺点?

MySQL断言

java - HQL返回数据类型

mysql - SQL:计算一个表的某个字段到同表的另一个字段的重复次数

php - 无法从 mysql 表中获取所有值

java - 使用 Java 将泰卢固语文本保存到 Oracle DB

php - Laravel 关系返回 null