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 也能正常工作,那就太好了。
在这方面我有一个相当坏的消息要告诉你
一旦看到 FULLTEXT 索引,MySQL 查询优化器往往会偏离进一步优化。我之前在 StackExchange 中写过这个
May 23, 2011
:https : //stackoverflow.com/a/6092216/491757Oct 25, 2011
: FULLTEXT 索引在 BOOLEAN MODE 中被忽略,“字数”有条件Jan 26, 2012
: mysql全文搜索my.cnf优化May 07, 2012
:MySQL EXPLAIN 不显示 FULLTEXT 的“使用索引”您将重构查询
我的建议是执行以下操作之一
这是您的原始查询:
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 计划。查询应执行以下操作:
Check Distance
按距离对结果进行排序如前所述,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)
对于 SQL Server,我们可以选择FORCE ORDER提示。我所知道的唯一可比的 MySQL 是STRAIGHT_JOIN。
STRAIGHT_JOIN 与 JOIN 类似,只是左表总是在右表之前被读取。这可用于连接优化器将表以错误顺序放置的那些(少数)情况。
但是,我倾向于建议,如果您通过使用子查询获得所需的结果,请坚持使用它。
归档时间: |
|
查看次数: |
1990 次 |
最近记录: |