有没有办法向 MySQL 的查询优化器提示应该首先完成哪些约束?

use*_*951 6 mysql optimization subquery

这是我当前的查询:

SELECT BusinessID as ID,  
  111151.29341326*SQRT(pow(-6.186751-X(LatLong),2)+pow(106.772835-Y(LatLong),2)*0.98838574205337) AS Distance from
(
    SELECT *
    FROM
      tableauxiliary
    WHERE
      MBRContains(
    GeomFromText (
        'MULTIPOINT(-6.1934985598076 106.76604791159,-6.1800034401924 106.77962208841)'
        ),
        Latlong)=1  
    AND Prominent >15 
) AS TA

    Having Distance <= 18238
    ORDER BY
  Distance
LIMIT
  0, 45
Run Code Online (Sandbox Code Playgroud)

请注意,他们我使用了子查询。它使用子查询的原因是因为我想要

      MBRContains(
    GeomFromText (
        'MULTIPOINT(-6.1934985598076 106.76604791159,-6.1800034401924 106.77962208841)'
        ),
        Latlong)=1   
Run Code Online (Sandbox Code Playgroud)

首先要完成。这将查询时间从 19 秒减少到 0.9 秒。

有没有办法提示mysql查询优化器,这样我就不需要使用子查询

更新:

我试过:

SELECT BusinessID as ID,  
  111151.29341326*SQRT(pow(-6.186751-X(LatLong),2)+pow(106.772835-Y(LatLong),2)*0.98838574205337) AS Distance from tableauxiliary 
USE Index (LatLong_2,FullTextSearch)
WHERE
    MBRContains(
    GeomFromText (
        'MULTIPOINT(-6.1934985598076 106.76604791159,-6.1800034401924 106.77962208841)'
        ),
        Latlong)  
    AND Prominent >15 
    AND MATCH FullTextSearch AGAINST ('a*' IN BOOLEAN MODE)
    ORDER BY
  Distance
Run Code Online (Sandbox Code Playgroud)

没变化。如果我使用解释 FullTextSearch 是唯一使用的索引。

注意:问题确实是关于速度的。发生的事情是我确信如果 mysql 优化器在 fulltextsearch 之前先做空间,查询会运行得更快。这是因为有时我们在全文搜索中搜索 a* 显然不受太多限制。

基本上我有全世界的企业数据库,我最多只对500平方米或10平方公里以内的企业感兴趣。因此,空间部分显然会受到更多限制。

当我转向 mongodb 时,如果 mysql 也能正常工作,那就太好了。

Rol*_*DBA 8

在这方面我有一个相当坏的消息要告诉你

一旦看到 FULLTEXT 索引,MySQL 查询优化器往往会偏离进一步优化。我之前在 StackExchange 中写过这个

您将重构查询

我的建议是执行以下操作之一

建议#1

  • 检索使用 FULLTEXT 搜索的企业 ID
  • 对检索到的 ID 执行地理空间搜索

建议#2

  • 使用地理空间搜索检索企业 ID(因为您说需要 0.9 秒)
  • 对地理空间检索的企业 ID 执行全文搜索

建议#3

  • 在 Subquery1 中使用地理空间搜索(因为您说需要 0.9 秒)检索企业 ID
  • 在 Subquery2 中使用 FULLTEXT 搜索检索企业 ID
  • INNER JOIN Subquery1 和 Subquery2

建议 #4

  • 使用地理空间搜索检索企业 ID(因为您说需要 0.9 秒)
  • 不要使用 FullTextSerach。对地理空间检索的企业 ID 使用 REGEXP

这是您的原始查询:

SELECT BusinessID as ID,  
    111151.29341326*SQRT(pow(-6.186751-X(LatLong),2)+
    pow(106.772835-Y(LatLong),2)*0.98838574205337) AS Distance
from tableauxiliary 
USE Index (LatLong_2,FullTextSearch)
WHERE
    MBRContains(
    GeomFromText (
        'MULTIPOINT(-6.1934985598076 106.76604791159,-6.1800034401924 106.77962208841)'
        ),
        Latlong)  
    AND Prominent >15 
    AND MATCH FullTextSearch AGAINST ('a*' IN BOOLEAN MODE)
    ORDER BY
  Distance;
Run Code Online (Sandbox Code Playgroud)

如果 MySQL Query Optimizer 检测到一个FULLTEXT搜索以及AND同一WHERE个子句中的后跟表达式的连接(因此,在 EXPLAIN 计划中的评估级别相同),则 MySQL Query Optimizer 将在使用 FULLTEXT 搜索后休假。

也许你可以尝试这样的事情(来自 SUGGESTION #1):

SELECT BusinessID as ID,  
    111151.29341326*SQRT(pow(-6.186751-X(LatLong),2)+
    pow(106.772835-Y(LatLong),2)*0.98838574205337) AS Distance
FROM
(
    SELECT BusinessID,LatLong
    FROM
    (
        SELECT BusinessID,Prominent,LatLong
        From tableauxiliary WHERE
        MATCH FullTextSearch AGAINST ('a*' IN BOOLEAN MODE)
    ) AA
    WHERE Prominent > 15
) A
WHERE
    MBRContains(
    GeomFromText (
        'MULTIPOINT(-6.1934985598076 106.76604791159,-6.1800034401924 106.77962208841)'
        ),
        Latlong)  
ORDER BY
    Distance
;
Run Code Online (Sandbox Code Playgroud)

请注意,您没有看到连词AND。请检查 EXPLAIN 计划。查询应执行以下操作:

  • 收集与 FULLTEXT 搜索匹配的 BusinessID、Prominent、LatLong
  • 删除 BusinessID,LatLong 其突出值 < 15
  • 检查剩余 BusinessID 值的距离
  • Check Distance按距离对结果进行排序

更新 2012-08-08 11:30 EDT

如前所述,FULLTEXT 索引似乎放弃了使用其他索引的所有希望。可能是两个被连接的子查询(建议 #3)

SELECT BusinessID as ID,  
    111151.29341326*SQRT(pow(-6.186751-X(LatLong),2)+
    pow(106.772835-Y(LatLong),2)*0.98838574205337) AS Distance
FROM
(
    SELECT BusinessID,Prominent From tableauxiliary WHERE
    MATCH FullTextSearch AGAINST ('a*' IN BOOLEAN MODE)
) A
INNER JOIN
(
    SELECT BusinessID From tableauxiliary WHERE
    MBRContains(
    GeomFromText (
        'MULTIPOINT(-6.1934985598076 106.76604791159,-6.1800034401924 106.77962208841)'
        ),
        Latlong)
) B
USING (BusinessID)
WHERE Prominent > 15
ORDER BY
    Distance
;
Run Code Online (Sandbox Code Playgroud)

您可能想完全放弃使用 FULLTEXT 搜索并尝试使用正则表达式(建议 #4)

SELECT B.BusinessID as ID,  
    111151.29341326*SQRT(pow(-6.186751-X(B.LatLong),2)+
    pow(106.772835-Y(B.LatLong),2)*0.98838574205337) AS Distance
FROM
(
    SELECT BusinessID From tableauxiliary WHERE
    MBRContains(
    GeomFromText (
        'MULTIPOINT(-6.1934985598076 106.76604791159,-6.1800034401924 106.77962208841)'
        ),
        Latlong)
) A INNER JOIN tableauxiliary B USING (BusinessID)
WHERE B.Prominent > 15 AND
((B.FullTextSearch REGEXP ' a*') OR (B.FullTextSearch REGEXP '^a*'))
ORDER BY
    Distance
;
Run Code Online (Sandbox Code Playgroud)


Mar*_*ith 5

对于 SQL Server,我们可以选择FORCE ORDER提示。我所知道的唯一可比的 MySQL 是STRAIGHT_JOIN

STRAIGHT_JOIN 与 JOIN 类似,只是左表总是在右表之前被读取。这可用于连接优化器将表以错误顺序放置的那些(少数)情况。

但是,我倾向于建议,如果您通过使用子查询获得所需的结果,请坚持使用它。