我只是想抓紧剖析。
我之前有一个简单的查询优化,但是这个有更多的参与,所以我不确定在这种情况下我可能需要添加索引的哪些列!
SELECT ReportID, Title, Description, postPic , DatePosted, UserID, FName, SName, authorNotificationId, userPic, Lat, `Long`,
photoWidth, photoHeight
FROM
(SELECT
(((acos(sin((?*pi()/180))
* sin((`Lat`*pi()/180))+cos((?*pi()/180))
* cos((`Lat`*pi()/180)) * cos(((?- `Long`)
*pi()/180))))*180/pi())*60*1.1515*1609.34)
AS distance, Title, Description, posts.Pic as postPic, ReportID, DatePosted, posts.UserID as UserID, FName, SName, NotificationID as authorNotificationId, users.Pic as userPic,
Lat, `Long`, photoWidth, photoHeight
FROM posts
INNER JOIN Users
ON Users.UserID = posts.UserID) foo
WHERE distance <=? AND (Title LIKE ? OR Description LIKE ? OR FName LIKE ? OR SName LIKE ?)
ORDER BY DatePosted DESC LIMIT ?, 10
查询的简要说明:它尝试检索用户预定半径内的所有帖子 - 通过检查用户注册位置的坐标与帖子的相关坐标之间的距离(并检查该距离是否小于用户的注册半径)
运行说明给我以下内容:
id : 1
select_type : Primary
table : <derived2>
type : **ALL**
possible_keys : NULL
key : NULL
key_len : NULL
ref : NULL
rows : 824
Extra : Using where; **Using filesort**
id : 2
select_type : DERIVED
table : tableposts
type : ALL
possible_keys : NULL
key : NULL
key_len : NULL
ref : NULL
rows : 824
Extra : NULL
id : 2
select_type : DERIVED
table : Users
type : eq_ref
possible_keys : PRIMARY
key : PRIMARY
key_len : 4
ref : db.posts.UserID
rows : 1
Extra : NULL
由于 ALL select_type和额外的 filesort ,我只需要担心查询1和2。
我是否必须在列标题和说明中添加索引?我已经在users表中有一个关于fname和sname的索引。
正如Olli指出的那样,距离是计算的结果,因此我无法为该
添加索引更新
从Olli的回答中,我从EXPLAIN中得到以下信息:
id : 1
select_type : SIMPLE
table : posts
type : ALL
possible_keys: postsUserID_idx
key : NULL
key_len : NULL
ref : NULL
rows : 825
Extra : Using where; Using filesort
id : 1
select_type : SIMPLE
table : Users
type : eq_ref
possible_keys: PRIMARY
key : PRIMARY
key_len : 4
ref : db.posts.UserID
rows : 1
Extra : Using where
更新2:
根据symcbean的建议,表重组的初始尝试是添加另一个类型为point的col:
set @lat= 53.277656872106;
set @lon = -9.01179972749435;
set @dist = CONV_MI_KM(50000, 'k')/1000;
set @rlon1 = @lon-@dist/abs(cos(radians(@lat))*69);
set @rlon2 = @lon+@dist/abs(cos(radians(@lat))*69);
set @rlat1 = @lat-(@dist/69);
set @rlat2 = @lat+(@dist/69);
//set @geoCol = astext(envelope(linestring(point(@rlon1, @rlat1), point(@rlon2, @rlat2))));
set @geoCol = astext(linestring(point(@rlon1, @rlat1), point(@rlon2, @rlat2)));
set @geoCol2 = linestring(point(@rlon1, @rlat1), point(@rlon2, @rlat2));
我需要更改我的注册准备语句:
INSERT INTO users VALUES
('', ?, ?, ?, ?, ?, ?, ?, 0, ?, ?, 0, ?, 0)
在0之后的表格末尾包含newCol。这应该是我定义为geoCol2的吗?不确定的原因是在php中绑定param我认为我可能需要使用“s”作为绑定类型,就像查找可以绑定到语句的params类型时一样,我只看到s,i, d和b作为选项。还是我不在标记?
答案 0 :(得分:0)
您是以英里还是公里计算距离?
你可以试试这个查询(应该是相同的,只有没有子查询):
SELECT
(((acos(sin((?*pi()/180))
* sin((`Lat`*pi()/180))+cos((?*pi()/180))
* cos((`Lat`*pi()/180)) * cos(((?- `Long`)
*pi()/180))))*180/pi())*111189.3006) AS distance,
ReportID,
Title,
Description,
postPic ,
DatePosted,
UserID,
FName,
SName,
authorNotificationId,
userPic,
Lat,
`Long`,
photoWidth,
photoHeight
FROM
posts
JOIN Users ON (Users.UserID = posts.UserID)
WHERE (Title LIKE ? OR Description LIKE ? OR FName LIKE ? OR SName LIKE ?)
HAVING distance <= ?
ORDER BY
DatePosted DESC LIMIT ?, 10
由于您在运行中计算距离,因此您需要使用HAVING子句进行检查,否则对于WHERE,它将因未知列而失败。
你也可以为这个添加执行计划吗?