我有一个非常简单的表来记录来自传感器的读数。有一列表示传感器id号,一列表示传感器读数,另一列表示时间戳。此列的SQL类型为Timestamp。表中有大量数据,有几百万行。
当我使用某个传感器id号查询某个时间戳之前的所有行时,有时会花费很长时间。如果时间戳是很久以前的时间戳,则查询速度相当快,但如果是最近的时间戳,则可能需要2到3秒。
看起来好像SQL引擎正在对表进行迭代,直到它找到第一个大于查询时间戳的时间戳。或者可能更多的查询数据减慢了它的速度,我不知道。
无论如何,我在这里寻找设计建议,特别是针对以下几点:为什么它这么慢?我怎么才能让它更快呢?
有没有什么设计技巧可以应用在这里?我对SQL了解不多,也许有一种方法可以让SQL引擎知道数据是有序的(目前还没有,但我想我可以在插入时对其进行排序),并加快查询速度。也许我应该改变查询的方式,或者改变时间戳列的数据类型。
发布于 2018-04-24 20:32:37
使用EXPLAIN
查看执行计划,并验证查询是否使用了合适的索引。如果没有,请验证是否有适当的索引可用。
INDEX
是“按顺序”存储的,MySQL可以有效地使用某些查询模式。( InnoDB表也按集群键顺序存储,这是表的主键(如果存在)或非空列上的第一个唯一键。)
对于某些查询模式,通过使用索引,MySQL可以消除对大量行的检查。当MySQL不能使用索引时(因为合适的索引不存在,或者因为查询具有阻止它的构造),执行计划将执行完全扫描,即检查表中的每一行。当这种情况发生在非常大的表上时,有一种变慢的趋势。
编辑
问:为什么它这么慢?
答:影响运行时间的因素有几个。它可能是争用,例如,由另一个会话占用的排他表锁,或者可能是I/O (磁盘读取)的时间,或者是一个大型的“使用文件排序”操作。通过慢速网络连接返回结果集的时间。
由于所提供的信息有限,无法诊断问题。我们只能就一些常见的问题提供一些建议。
问:我如何才能让它更快?
答:不可能提出具体的建议。我们需要找出瓶颈在哪里,瓶颈是什么,以及瓶颈所在的地址。
查看EXPLAIN
的输出以检查执行计划。是否使用了适当的索引,或者是否正在执行完全扫描?检查了多少行?是否有“使用文件排序”操作?等人提出的。
问:有没有可以在这里应用的设计技术?
答:通常情况下,拥有适当的索引,并仔细设计SQL语句,以便启用最有效的访问计划。
问:也许我应该改变查询的方式
答:更改SQL语句可能会提高性能,在查看了执行计划之后,这是一个很好的起点……是否可以修改查询以获得更有效的计划?
问:或者更改时间戳列的数据类型。
答:我认为更改TIMESTAMP列的数据类型不太可能提高性能。这只有4个字节。您会将其更改为什么?使用DATETIME
将占用7个字节。
通常,我们希望行尽可能短,并将尽可能多的行打包到一个块中。它还希望以一种物理方式组织表,以便可以从较少的块满足查询……查询所需的行是在较少的页面中找到的,而不是分散在大量页面上的行。
对于InnoDB,增加缓冲池的大小可能会减少I/O。
来自固态硬盘(SSD)的I/O将比来自旋转硬盘( HDD )的I/O更快,如果HDD上存在来自其他进程的I/O争用,这一点尤其正确。
https://stackoverflow.com/questions/50010194
复制