寻找最接近的值。如何告诉MySQL数据已经排序?

寻找最接近的值。如何告诉MySQL数据已经排序?,mysql,Mysql,假设我有一张如下所示的桌子: +-----------+------------+------+-----+---------+ | Field | Type | Null | Key | Default | +------------+------------+------+-----+---------+ | datetime | double | NO | PRI | NULL | | some_value | float | NO

假设我有一张如下所示的桌子:

+-----------+------------+------+-----+---------+
| Field     | Type       | Null | Key | Default |
+------------+------------+------+-----+---------+
| datetime   | double     | NO   | PRI | NULL    |
| some_value | float      | NO   |     | NULL    |
+------------+------------+------+-----+---------+
日期必须是双精度的,并且在unix时间中以小数秒注册。不可能安装mysql 5.6来使用小数日期时间。此外,datetime字段的值不仅是主要的,而且总是在增加。我想找到最接近某个值的行。通常,您可以使用以下内容:

select * from table order by abs(datetime - $myvalue) limit 1
但是,我担心这个实现对于数十万个值来说会很慢,因为它将在所有数据库中搜索。因为我有一个有序的列表,我知道我可以做一些二进制搜索来加速这个过程,但是我不知道如何告诉MySQL执行这种搜索

为了测试性能,我执行以下步骤:

SET profiling = 1;
SELECT * FROM table order by abs(datetime - $myvalue) limit 1;
SHOW PROFILE FOR QUERY 1;
结果如下:

+--------------------------------+----------+
| Status                         | Duration |
+--------------------------------+----------+
| starting                       | 0.000122 |
| Waiting for query cache lock   | 0.000051 |
| checking query cache for query | 0.000191 |
| checking permissions           | 0.000038 |
| Opening tables                 | 0.000094 |
| System lock                    | 0.000047 |
| Waiting for query cache lock   | 0.000085 |
| init                           | 0.000103 |
| optimizing                     | 0.000031 |
| statistics                     | 0.000057 |
| preparing                      | 0.000049 |
| executing                      | 0.000023 |
| Sorting result                 | 2.806665 |
| Sending data                   | 0.000359 |
| end                            | 0.000049 |
| query end                      | 0.000033 |
| closing tables                 | 0.000050 |
| freeing items                  | 0.000089 |
| logging slow query             | 0.000067 |
| cleaning up                    | 0.000032 |
+--------------------------------+----------+
根据我的理解,排序结果需要2.8秒,但是我的数据已经排序了。作为补充信息,我有大约240000行。

尝试将其设置为字段:

select abs(datetime - $myvalue) as date_diff, table.*
from table
order by date_diff
limit 1

RDBMS中支持索引。在您感兴趣的日期、时间或字段上定义索引,db不会执行完整的表扫描

它不会扫描整个数据库。主键由B树索引。如果你能做到的话,强迫它进行二进制搜索会更慢,但你不能做到。

我的查询已经给出了我想要的结果。这不是问题所在。问题是,我知道我的数据是有序的,因此,当我有一个类似于二进制搜索的实现时,二进制搜索会快得多,根据需要拆分表,执行接近Olog的速度比什么快?我已经在datetime字段中有一个主索引,如问题中所示。但是,我不知道任何增量键只有auto_increment,这不是告诉mysql更有效地找到值的情况。有没有办法提高性能?因为我知道这张桌子已经订好了。因为否则会导致大量不必要的计算。从什么方面提高性能?您有何证据表明存在性能问题?你对那个问题做过解释吗?除了猜测之外还做了什么?这是解释命令1 | SIMPLE | table | u name | ALL | NULL | NULL | NULL | 236683行|使用文件排序的结果。正如您所说,MySQL对每个字段都执行absdatetime-$myvalue是一种猜测,因为我无法看到其他方法来跳过该操作而不告诉它。我会详细核实。无论如何,它让我感到疑惑,因为查询需要2.8秒,但它是在RPI3中。我很困惑,你认为它可以在什么上执行这个二进制切分。如果有WHERE子句,它可以匹配索引中的那些值或范围,但是如果没有,就没有什么可搜索的,或者二进制切块。事实上,我以大约4Hz的频率获取数据。然后我存储数据的信息,时间(以分秒为单位)和我收到的值。一旦数据被存储,在某一点上,我需要获取在请求的时间接收到的值,该时间与存储的时间不完全相同,这就是为什么我需要最接近的时间。由于数据是有序的,所以我相信每次搜索时数据都会被切成两半。