【问题标题】:Most efficient way to find the closest integer in MySQL?在 MySQL 中找到最接近整数的最有效方法?
【发布时间】:2009-08-20 11:58:18
【问题描述】:

我在 MySQL 数据库中有一个表,我想从中选择时间戳与另一个给定时间戳最接近的行。

time 是时间戳列(整数 UNIX 时间戳)。我随意选择了1250710000

这是我提出的查询,我想知道是否有更有效的方法:

SELECT *, ABS(time - 1250710000) AS time_dist FROM table
 ORDER BY time_dist ASC LIMIT 1

这是最好的方法吗?

【问题讨论】:

    标签: mysql performance


    【解决方案1】:

    假设time被索引,你几乎可以免费获得next记录:

    SELECT * FROM table WHERE time > 1250710000 ORDER BY time LIMIT 1
    

    如果我没记错的话,前面的记录也是如此,MySQL 只会以相反的顺序读取索引。使用两者的 UNION,按日期差异排序,瞧!结果将如下所示

    SELECT *
    FROM
    (
        (SELECT *, ABS(time - 1250710000) AS time_diff FROM table WHERE time > 1250710000 ORDER BY time ASC LIMIT 1)
        UNION ALL
        (SELECT *, ABS(time - 1250710000) AS time_diff FROM table WHERE time < 1250710000 ORDER BY time DESC LIMIT 1)
    ) AS tmp
    ORDER BY time_diff
    LIMIT 1
    

    理想情况下,您应该使用 &gt;=&lt;= 而不是 &gt;&lt;,并使用其主 ID 排除参考记录,以说明共享相同时间戳的记录。

    【讨论】:

    • 好主意,但参考时间戳(在本例中为1250710000)不在同一个表中。话虽如此,我假设这个查询在效率方面大致相同?
    • @cyouung: 这个查询在效率上不一样。您的查询对每一行执行ABS(time - 125071000)。只要您在time 上有索引,此查询将永远不会读取超过两行。
    【解决方案2】:

    正如埃文所说,你拥有它的方式很好。我会推荐一个关于该时间戳字段的索引,以便 MySQL 可以扫描较小的索引而不是整个表。另外,我会尝试一些“拳击”,看看索引是否可以加快速度:

    SELECT *, ABS(time - 1250710000) AS time_dist FROM table 
    WHERE time between(1250610000,1250810000)
    ORDER BY time_dist ASC LIMIT 1
    

    上述查询限制为大约 +/- 1 天。您必须做一些基准测试,看看额外的索引扫描(where 子句)是否比在表中的所有条目上计算 ABS() 更快。

    【讨论】:

    • 我不喜欢这样的任意限制。
    【解决方案3】:

    选择更大的最小时间和最大时间会更有效吗? 比这两个更小的时间。那应该避免必须在 整张桌子。

    SELECT MAX(time) AS prev WHERE time

    SELECT MIN(time) AS next WHERE time > 1250710000;

    选择最小值(ABS(上一个),ABS(下一个));

    我的 SQL 不够强大,无法将它们合并为一个,并且三个的开销 查询可能会扼杀任何节省,但有可能。

    【讨论】:

      猜你喜欢
      • 2012-02-29
      • 1970-01-01
      • 2021-10-05
      • 2011-01-15
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      相关资源
      最近更新 更多