使多子选择更有效率?

时间:2015-06-09 19:53:14

标签: mysql sql query-optimization

我有一个select查询,它按字母顺序返回与给定ID相关的下一条记录:

SELECT * 
FROM contacts 
WHERE client_id = 22844 
AND deleted_at IS NULL 
AND 
( 
  ( 
    last_name = (
      SELECT last_name 
      FROM contacts 
      WHERE client_id = 22844 AND id = 717604
    ) 
    AND first_name > (
      SELECT first_name 
      FROM contacts 
      WHERE client_id = 22844 AND id = 717604
    )
  ) 
  OR ( 
    last_name > (
      SELECT last_name 
      FROM contacts 
      WHERE client_id = 22844 AND id = 717604
    ) 
  ) 
) 

ORDER BY last_name, first_name 
LIMIT 1

first_name,last_name,deleted_at和client_id都有单独的索引。

有没有办法重写这个更高效?当特定客户有大约3000个联系人时,它目前大约需要250毫秒到300毫秒。

目前正在使用mysql 5.5

编辑:

如果我忽略deleted_at IS NULL条件,结果会快一个数量级。我可能会停止使用软删除并将删除的记录移到存档中。

2 个答案:

答案 0 :(得分:1)

这是另一种方法。它会在看到所需的行之后枚举行:

SELECT c.*
FROM (SELECT c.*,
             (@rn := if(c.id = 717604 or @rn > 0, @rn + 1, 0) as rn                
      FROM contacts c CROSS JOIN
           (SELECT @rn := 0) params
      WHERE c.client_id = 22844 AND c.deleted_at IS NULL 
      ORDER BY c.last_name, c.first_name
     ) c
WHERE rn = 2;

对于此查询,您需要contacts(client_id, deleted_at, last_name, first_name)上的索引。

编辑:

您查询的效果似乎合理。但是,最佳索引是contacts(client_id, id, last_name)contacts(client_id, id, first_name)

答案 1 :(得分:0)

    sql := "INSERT INTO users set user_nickname='?', user_first='?', user_last='?', user_email='?'"
    q, err := db.Exec(sql, NewUser.Name, NewUser.First, NewUser.Last, NewUser.Email)