我有一个非常简单的表来记录传感器的读数。这里有一列传感器ID号,一列用于传感器读数,一列用于时间戳。此列是SQL类型Timestamp。表中有大量数据,几百万行。
当我在具有特定传感器ID号的特定时间戳之前查询所有行时,有时可能需要很长时间。如果时间戳是过去的,那么查询速度非常快,但如果它是最近的时间戳,则最多可能需要2到3秒。
看起来好像SQL引擎正在迭代表,直到它找到第一个大于查询时间戳的时间戳。或者也许更多的查询数据会减慢它的速度,我不知道。
无论如何,我在这里寻找设计建议,专门针对要点:为什么这么慢?我怎样才能让它更快?
有没有可以在这里应用的设计技巧?我不太了解SQL,也许有一种让SQL引擎知道数据是否有序的方法(现在它不是,但我可以在插入时订购它)并加快速度查询。也许我应该改变查询的方式或更改时间戳列的数据类型。
答案 0 :(得分:0)
使用EXPLAIN
查看执行计划,并验证查询是否使用了合适的索引。如果没有,请验证是否有适当的索引。
INDEX
按顺序存储,MySQL可以使用某些查询模式。 (InnoDB表也按顺序存储,通过集群密钥,即表的PRIMARY KEY(如果存在)或非NULL列上的第一个UNIQUE KEY。)
使用一些查询模式,通过使用索引,MySQL可以消除大量的行被检查。当MySQL无法创建索引的用户时(或者因为不存在合适的索引,或者因为查询具有阻止它的构造),执行计划将进行全面扫描,即检查表中的每个行。当这种情况发生在非常大的桌子上时,事情会变得缓慢。
修改强>
问:为什么这么慢?答:有几个因素会影响经过的时间。它可能是争用,例如,由另一个会话占用的独占表锁,或者它可能是I / O(磁盘读取)或大型“使用filesort”操作的时间。通过慢速网络连接返回结果集的时间。
使用提供的有限信息无法诊断问题。我们只能就一些常见问题提供一些建议。
问:我怎样才能让它更快?答:无法提出具体建议。我们需要弄清楚瓶颈的位置和内容以及地址。
查看EXPLAIN
的输出以检查执行计划。是使用了适当的索引,还是正在进行全面扫描?正在检查多少行?是否有“使用filesort”操作?等人。
答:通常,拥有适当的索引,并仔细制作SQL语句,以便启用最有效的访问计划。
问:也许我应该改变查询的完成方式
答:在查看执行计划后,更改SQL语句可能会提高性能,这是一个很好的起点...可以修改查询以获得更有效的计划吗?
问:或者更改时间戳列的数据类型。
答:我认为更改TIMESTAMP列的数据类型不太可能提高性能。那只有4个字节。你会把它改成什么?使用DATETIME
需要7个字节。
通常,我们希望行尽可能短,并将尽可能多的行打包到块中。还希望以一种方式对表进行物理组织,以便可以从更少的块中满足查询...查询所需的行可以在更少的页面中找到,而不是在大量页面上分散的二十几行。
使用InnoDB,增加缓冲池的大小可能会减少I / O.
来自固态硬盘(SSD)的I / O将比旋转硬盘(HDD)的I / O更快,如果其他进程的硬盘上存在I / O争用,则尤其如此。