【问题标题】:MySQL query time too long in sensor timestamped data table传感器时间戳数据表中的 MySQL 查询时间太长
【发布时间】:2018-04-24 20:22:05
【问题描述】:

我有一个非常简单的表格来记录传感器的读数。有一列用于传感器 ID 号,一列用于传感器读取,一列用于时间戳。此列是 SQL 类型的时间戳。表中有大量数据,几百万行。

当我使用某个传感器 ID 号查询某个时间戳之前的所有行时,有时可能需要很长时间。如果时间戳远在过去,则查询速度非常快,但如果是最近的时间戳,则最多可能需要 2 或 3 秒。

SQL 引擎似乎在对表进行迭代,直到找到大于查询时间戳的第一个时间戳。或者可能是大量的查询数据会减慢速度,我不知道。

无论如何,我在这里寻找设计建议,特别是要解决以下问题:为什么这么慢?我怎样才能让它更快?

这里有什么设计技巧可以应用吗?我对SQL不太了解,也许有一种方法可以让SQL引擎知道数据是有序的(现在不是,但我猜我可以在插入时对其进行排序)并加快查询速度。也许我应该改变查询完成的方式或者改变时间戳列的数据类型。

【问题讨论】:

  • "如果时间戳在很久以前,查询会很快,但如果是最近的时间戳,则最多可能需要 2 或 3 秒。" -> 您可能想升级到支持 DESC 索引的 MySQL 8.0 可能会加快对最近时间戳的搜索..
  • "看起来好像 SQL 引擎正在遍历表,直到它找到大于查询时间戳的第一个时间戳。或者可能大量的查询数据使其变慢,我不知道。”为过去的查询和最近时间戳的查询提供EXPLAIN [query],以便我们查看计划是否不同。

标签: mysql iot sensors


【解决方案1】:

使用EXPLAIN 查看执行计划,并验证查询是否使用了合适的索引。如果没有,请验证适当的索引是否可用。

INDEX 是“按顺序”存储的,MySQL 可以有效地使用某些查询模式。 (InnoDB 表也是按集群键顺序存储的,集群键是表的 PRIMARY KEY(如果存在)或非 NULL 列上的第一个 UNIQUE KEY。)

对于某些查询模式,通过使用索引,MySQL 可以避免检查大量行。当 MySQL 无法使用索引时(或者因为不存在合适的索引,或者因为查询有阻止它的结构),执行计划将进行全扫描,即检查 表格中的每一行。当这种情况发生在非常大的表上时,事情往往会变慢。

编辑

问:为什么这么慢?

答:有几个因素会影响经过的时间。可能是争用,例如,另一个会话占用了独占表锁,或者可能是 I/O(磁盘读取)时间,或大型“使用文件排序”操作。通过慢速网络连接返回结果集的时间。

使用提供的有限信息无法诊断问题。我们只能就一些常见问题提供一些建议。

问:我怎样才能让它更快?

答:无法提出具体建议。我们需要弄清楚瓶颈在哪里,什么是瓶颈,以及解决办法。

查看EXPLAIN 的输出以检查执行计划。是否使用了适当的索引,或者是否正在执行完整扫描?正在检查多少行?是否有“使用文件排序”操作?等。

问:这里有什么设计技巧可以应用吗?

答:一般来说,有一个适当的可用索引,并仔细设计 SQL 语句,以便启用最有效的访问计划。

问:也许我应该改变查询完成的方式

A:更改 SQL 语句可能会提高性能,这是一个很好的起点,在查看执行计划之后……可以修改查询以获得更有效的计划吗?

Q:或者更改时间戳列的数据类型。

答:我认为更改 TIMESTAMP 列的数据类型不太可能提高性能。那只有4个字节。你会把它改成什么?使用 DATETIME 需要 7 个字节。

一般来说,我们希望行尽可能短,并将尽可能多的行打包到一个块中。还希望以一种可以从更少的块中满足查询的方式对表进行物理组织......查询需要的行在更少的页面中找到,而不是将行分散在大量页面上。

对于 InnoDB,增加缓冲池的大小可能会减少 I/O。

并且来自固态驱动器 (SSD) 的 I/O 将比来自旋转硬盘 (HDD) 的 I/O 更快,如果其他进程在 HDD 上存在 I/O 争用,则尤其如此。

【讨论】:

  • 表扫描并不是按照定义慢,但它取决于您的表大小、查询、索引和源磁盘硬件。实际上在某些情况下使用索引(多个随机磁盘 i/o)可能比使用全表扫描(一个随机磁盘 i/o)成本更高。然后 MySQL 优化器将优先执行全表扫描。
  • @RaymondNijland;真的。对于 large 集,与使用索引查找和谓词 some_unique_indexed_col = some_val 进行查询的计划相比,完全扫描确实往往很昂贵(而且速度很慢)。我试图明确(在我的回答中)我们正在谈论一些可以利用 suitable i> 索引。我认为我在回答 not 时很小心,声称使用索引的执行计划总是比全表扫描更好(或更快)。但是鉴于 OP 对性能的模糊描述,并且没有提及任何索引...
  • ... 我怀疑 OP 正在查询的表上没有定义 any 索引,并且查询正在进行全面扫描。那只是推测,由于我们没有看到任何表或索引定义,我们不知道该表是不是 InnoDB,也没有看到任何 SQL 查询文本,我们无法做出具体的推荐。我们可以推荐使用EXPLAIN 来查看执行计划(这可能会导致 OP 查看 MySQL 参考手册),并至少提及适当索引可能带来的性能优势。
  • 真正使用具有良好唯一选择性或 MySQL 中所谓的基数的索引在大型数据集上的性能优于全表扫描。“我认为我在回答时很小心,没有提出任何要求使用索引的执行计划总是比全表扫描更好(或更快)。”当我读到“执行计划将要进行全扫描,即检查表中的每一行。当这种情况发生在大桌子上时,事情会变得很慢。”
猜你喜欢
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2011-04-20
  • 2021-05-08
  • 1970-01-01
  • 1970-01-01
相关资源
最近更新 更多