Warning: file_get_contents(/data/phpspider/zhask/data//catemap/0/svn/5.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
Mysql 改进SQL查询以获取特定日期的传感器事件&;设备类型_Mysql - Fatal编程技术网

Mysql 改进SQL查询以获取特定日期的传感器事件&;设备类型

Mysql 改进SQL查询以获取特定日期的传感器事件&;设备类型,mysql,Mysql,我们有一个事件mysql表,其中存储了从不同类型的传感器生成的事件。下面是同一个表的CREATETABLE查询 CREATE TABLE `event` ( `id` varchar(36) NOT NULL, `device_id` varchar(36) NOT NULL, `device_type` varchar(45) NOT NULL, `data` text NOT NULL, `created_at` datetime NOT NULL, PRIMAR

我们有一个事件mysql表,其中存储了从不同类型的传感器生成的事件。下面是同一个表的CREATETABLE查询

  CREATE TABLE `event` (
  `id` varchar(36) NOT NULL,
  `device_id` varchar(36) NOT NULL,
  `device_type` varchar(45) NOT NULL,
  `data` text NOT NULL,
  `created_at` datetime NOT NULL,
  PRIMARY KEY (`id`),
  UNIQUE KEY `id_UNIQUE` (`id`),
  KEY `fk_event_device_idx` (`device_id`),
  KEY `event_device_type` (`device_type`),
  KEY `event_created_at_idx` (`created_at`),
  CONSTRAINT `fk_event_device` FOREIGN KEY (`device_id`) REFERENCES `device` (`id`) ON DELETE NO ACTION ON UPDATE NO ACTION
) ENGINE=InnoDB DEFAULT CHARSET=utf8 |
我们有一个来自设备表的设备id外键,设备表有一个来自区域表的区域id外键

我们希望获取特定区域和设备类型(例如THL传感器)的事件,以确定日期(例如2017-02-26)。下面是我正在运行的查询,以执行相同的操作

select e.data from event e 
left join device d on d.id = e.device_id 
where d.type = 'mdc' and d.zone_id = 'e451b2a1-5f6c-4a75-8038-30854926a9c0' and DATE(e.created_at) = '2018-03-01';
+----+-------------+-------+------------+------+--------------------------------------+---------------------+---------+--------------+------+----------+------------------------------------+
    | id | select_type | table | partitions | type | possible_keys                        | key                 | key_len | ref          | rows | filtered | Extra                              |
    +----+-------------+-------+------------+------+--------------------------------------+---------------------+---------+--------------+------+----------+------------------------------------+
    |  1 | SIMPLE      | d     | NULL       | ref  | PRIMARY,id_UNIQUE,fk_device_zone_idx | fk_device_zone_idx  | 110     | const        |   23 |    10.00 | Using index condition; Using where |
    |  1 | SIMPLE      | e     | NULL       | ref  | fk_event_device_idx                  | fk_event_device_idx | 110     | senzopt.d.id |  197 |   100.00 | Using where                        |
    +----+-------------+-------+------------+------+--------------------------------------+---------------------+---------+--------------+------+----------+------------------------------------+
解释计划给出了以下相同的结果

select e.data from event e 
left join device d on d.id = e.device_id 
where d.type = 'mdc' and d.zone_id = 'e451b2a1-5f6c-4a75-8038-30854926a9c0' and DATE(e.created_at) = '2018-03-01';
+----+-------------+-------+------------+------+--------------------------------------+---------------------+---------+--------------+------+----------+------------------------------------+
    | id | select_type | table | partitions | type | possible_keys                        | key                 | key_len | ref          | rows | filtered | Extra                              |
    +----+-------------+-------+------------+------+--------------------------------------+---------------------+---------+--------------+------+----------+------------------------------------+
    |  1 | SIMPLE      | d     | NULL       | ref  | PRIMARY,id_UNIQUE,fk_device_zone_idx | fk_device_zone_idx  | 110     | const        |   23 |    10.00 | Using index condition; Using where |
    |  1 | SIMPLE      | e     | NULL       | ref  | fk_event_device_idx                  | fk_event_device_idx | 110     | senzopt.d.id |  197 |   100.00 | Using where                        |
    +----+-------------+-------+------------+------+--------------------------------------+---------------------+---------+--------------+------+----------+------------------------------------+
事件表中的记录总数约为500万条,执行上述查询并提供结果大约需要1秒。我希望提高sql执行时间。我们需要同样的建议。请让我知道我能做的一切


注意:我知道我也应该搬到NOSQL(Kafka/Cassandra/Spark)。为此,我们也在并行工作。但是,我希望改进查询,以便在当前环境下更好地为我的客户服务。

以下是您的查询,以更易读的格式重复:

SELECT
    e.data
FROM event e 
LEFT JOIN device d
    ON d.id = e.device_id 
WHERE
    d.type = 'mdc' AND
    d.zone_id = 'e451b2a1-5f6c-4a75-8038-30854926a9c0' AND
    DATE(e.created_at) = '2018-03-01';
我们可以通过添加适当的索引来提高此查询的性能,也可以对其进行重新表述

首先,您可以在
(类型,区域id)
上的
设备
表中创建一个复合索引。这对
WHERE
子句应该有帮助。请注意,假设
device.id
是该表的主键,它应该已经被索引,这意味着您的
LEFT JOIN
条件应该是最佳的

您还可以在
事件
表中的
事件.在
列中创建索引。但为了利用这一点,我们必须重写不可出售的条件
其中DATE(e.created_at)='2018-03-01'

WHERE e.created_at >= '2018-03-01' AND e.created_at < '2018-03-02'

就查询而言,WHERE子句中的谓词否定左连接的外部性。也就是说,
LEFT
关键字是多余的

在函数中包装列将禁用MySQL执行范围扫描操作的能力。状况

 DATE(e.created_date) = '2018-03-01'
导致MySQL为表中的每一行(或者至少是尚未被其他谓词消除的每一行)计算左侧的表达式,然后将结果与右侧的文本进行比较

为了能够有效地使用索引,最好将其写入引用裸列

     e.created_date >= '2018-03-01'
 AND e.created_date <  '2018-03-01' + INTERVAL 1 DAY
创建该索引后,我们可以在设备id上删除冗余索引。。。前导列为device_id的新索引足以支持外键约束

除非对事件(id)]上的冗余
id\u UNIQUE
索引[
有具体原因,否则我将删除它

不需要强制唯一性,主键约束已经做到了这一点。诚然,这可能是为一个有利的边缘情况创建的(在这种情况下,它是一个特定查询的覆盖索引。如果不这样做,它就不是必需的,并且会影响DML性能)

DROP INDEX id_UNIQUE ON event ;

对于这个查询,
设备
表上的有益索引是

... ON `event` (`device_id`, `created_date`)
`ON device (zone_id, device)`
我们希望MySQL在
Extra
列的解释输出中显示“使用索引”

有了合适的索引,我会把查询写得更清楚一点,消除多余的
LEFT
关键字

SELECT e.data 
  FROM event e

  JOIN device d
    ON d.id = e.device_id 
   AND d.type = 'mdc'
   AND d.zone_id = 'e451b2a1-5f6c-4a75-8038-30854926a9c0'

 WHERE e.created_at >= '2018-03-01'
   AND e.created_at <  '2018-03-01' + INTERVAL 1 DAY 
选择e.data
来自事件e
连接设备d
在d.id=e.device\u id上
和d.type='mdc'
和d.zone_id='e451b2a1-5f6c-4a75-8038-30854926a9c0'
其中e.创建于>='2018-03-01'
在<'2018-03-01'+间隔1天时创建e.U

为什么要在查询中保留
LEFT
关键字?WHERE子句中
d
列上的相等谓词意味着不会返回空值。结果相当于内部联接。@tim biegeleisen非常感谢!查询有了很大改进。为什么要从查询中删除
LEFT-join
d呈现您的建议不可行。@TimBiegeleisen左
关键字是假的…查询正在进行内部联接。我在查询实际进行外部联接时指定外部联接,而不是在其进行内部联接时指定外部联接。在不执行外部联接时指定外部联接对我来说没有意义。另外,基于pa根据我的经验,我不会依赖SQL优化器来认识到它是一个内部连接,并且可能会将自己约束到一个效率较低的计划中,以支持不必要的外部连接。(我知道优化器现在比5.1及更早版本中的优化器要好得多,但仍然……)你说得对,很好。我想主要的区别是,强制左连接会强制扫描一个表而不是另一个表,而实际上扫描另一侧可能会更快。@TimBiegeleisen:没错。但在5.6及更高版本中,这对优化器来说可能不是问题……它可能会将其视为内部连接,但为什么要冒险呢另一个大问题是未来的读者,避免不必要的观察。@spencer7593非常感谢!这个查询改进了很多。