mysql优化内部连接的查询,其中和顺序和坐标

时间:2016-01-07 10:50:18

标签: mysql sql join sql-order-by query-optimization

我只是想抓紧剖析。

我之前有一个简单的查询优化,但是这个有更多的参与,所以我不确定在这种情况下我可能需要添加索引的哪些列!

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作为选项。还是我不在标记?

1 个答案:

答案 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,它将因未知列而失败。

你也可以为这个添加执行计划吗?