【问题标题】:Is there a Way to Optimize a MySQL Query that Runs a Function on Every Row?有没有办法优化在每一行上运行一个函数的 MySQL 查询?
【发布时间】:2010-06-21 22:24:23
【问题描述】:

我有一个 MySQL 查询,它根据标准从数据库中提取经纬度,测试这些点是否在多边形内,并返回多边形内的点。

一切正常。问题是查询大约需要。 20 秒返回结果。有没有办法优化这个查询,让查询速度更快?

SELECT latitude, longitude
FROM myTable
WHERE offense = 'green' AND myWithin(
POINTFROMTEXT( CONCAT( 'POINT(', latitude, ' ', longitude, ')' ) ) , POLYFROMTEXT( 'POLYGON(( ...bunch of lat longs...))' )
) = 1;

我运行了一个 EXPLAIN SELECT... 它产生了

标识 |选择类型 |表|类型 | 可能的键 |关键 | key_len |参考 | 行 |额外的

1 SIMPLE myTable ALL NULL NULL NULL NULL 137003 使用where

有没有一种方法可以优化在数据库中的每个纬度和经度上运行的查询,或者这是否尽可能好?

我正在考虑对另一个表进行选择,然后查询结果表,但我希望有一种方法可以提高此查询的性能。

如果有人有任何建议或想法,我很乐意听到。

谢谢,

拉克西米迪

【问题讨论】:

    标签: mysql query-optimization


    【解决方案1】:

    多边形有多大?您可以在整个多边形周围定义一个“边界矩形”,然后执行以下操作:

    SELECT latitude, longitude
    FROM myTable
    WHERE
      offense = 'green' AND
      latitude BETWEEN rect_left AND rect_right AND
      longitude BETWEEN rect_top AND rect_bottom AND
      myWithin(
        POINTFROMTEXT( CONCAT( 'POINT(', latitude, ' ', longitude, ')' ) ),
        POLYFROMTEXT( 'POLYGON(( ...bunch of lat longs...))' )) = 1;
    

    这样,它可以使用纬度和经度索引来缩小运行复杂数据所需的点数。

    【讨论】:

    • 嗨,codeka,多边形是邻域。而且它们的形状不规则。有没有办法运行 MBRContains 和 myWithin 函数?据我了解,MBRContains 给出了误报。它会给出假阴性吗?如果没有,也许这将是一个解决方案。如果有一种方法可以将 MBRContains 与 myWithin 函数一起使用,那么我就可以避免为每个邻域添加用于边界矩形的列。喜欢听听你的想法。我认为“边界矩形”是个好主意。
    • 您不必为边界矩形添加列,它很容易计算。只要拿你的“一堆经纬度”并计算最小和最大纬度 - 分别是'rect_left'和'rect_right'。 “bunch of lat longs”的最小和最大经度分别是“rect_bottom”和“rect_top”。您可以在运行查询之前简单地计算一下。
    • 您好,院长,感谢您的留言。很好的一点。我没有想到。问题解决了。非常感谢。
    【解决方案2】:

    我看到了两种明显的优化途径:

    • 在运行函数 O(n) 次之前进一步减少结果集。现在您正在运行该函数 137003 次 - 如果您无法进一步过滤结果集,则几乎没有办法避免这种情况。

    • 使函数更快,这样您仍然运行它 137k 次,但每次调用花费的时间更少,从而减少了您的总运行时间。

    现在,您的函数每行需要 0.1459 毫秒才能运行,这确实不错。您可能想尝试找到一些方法来进一步减少您必须运行它的行数。通过巧妙地使用 WHERE 来减少结果集还有一个附带好处是允许您的数据库为您做一些优化,这就是您想要使用它的方式。

    【讨论】:

    • 嗨,尼克,感谢您的留言。我很高兴我的功能运行得相当快。我将不得不努力减少函数必须运行的次数。非常感谢您的帮助。
    猜你喜欢
    • 2021-10-27
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2018-08-15
    • 2020-03-21
    • 2020-06-09
    相关资源
    最近更新 更多