从mysql获取数据,耗时将近436秒

时间:2018-10-24 08:38:51

标签: mysql performance query-optimization

我是android开发人员,对mysql没有太多经验。我在mysql数据库中有3个表。

第一个表:- UserTable

+-------------+-------------+----------+----------------------+
| user_id     | name      |   image    |   joining_date       |
+-------------+-------------+----------+----------------------+
|         100 | King      | defualt.jpg | 2018-05-23 20:09:27 |
|         101 | Kochhar   | defualt.jpg | 2018-05-23 20:09:27 |
| - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - |
| - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - |

第二表:- friendRequests

+-------------+-------------+----------+
| unique_id   | from_id     |   to_id  |
+-------------+-------------+----------+
|         1  | 100          | 101      |
|         2  | 200          | 110      |
| - - - - - - - - - - - - - - - - - - -|
| - - - - - - - - - - - - - - - - - - -|

第三张表:- 朋友

+-------------+-------------+----------+
| unique_id   | from_id     |   to_id  |
+-------------+-------------+----------+
|         1  | 104          | 101      |
|         2  | 206          | 110      |
| - - - - - - - - - - - - - - - - - - -|
| - - - - - - - - - - - - - - - - - - -|

我想获取不是我的朋友的用户列表,并且我们还没有待处理的朋友请求。所以我尝试了以下查询:-

SELECT usertable.name,
       usertable.user_id,
       usertable.image
FROM   `UserTable` AS usertable
WHERE  usertable.user_id <> '100'
       AND (SELECT Count(*)
            FROM   friendrequests
            WHERE  ( to_id = '100'
                     AND from_id = usertable.user_id )
                    OR ( to_id = usertable.user_id
                         AND from_id = '100' )) = 0
       AND (SELECT Count(*)
            FROM   friends
            WHERE  to_id = usertable.user_id
                   AND from_id = '100'
                    OR to_id = '100'
                       AND from_id = usertable.user_id) = 0
ORDER  BY usertable.joining_date DESC
LIMIT  10  

它正在工作,但是需要436秒。编写此查询的正确方法是什么?

1 个答案:

答案 0 :(得分:1)

这是另一种方法:

1)使用NOT IN

您在usertable.user_id上添加了不应包含在ID列表中的条件:这些ID都是具有{{1}的表friendrequestsfriends的ID }或to_id = 100。

from_id
根据里克·詹姆斯(Rick James)的评论,

编辑,但没有并集:

SELECT 
  usertable.name,
  usertable.user_id,
  usertable.image
FROM `UserTable` AS usertable
WHERE usertable.user_id <> '100'
  AND usertable.user_id NOT IN 
    (SELECT from_id as user_id FROM friendrequests WHERE to_id = '100'
     UNION
     SELECT to_id as user_id FROM friendrequests WHERE from_id = '100'
     UNION
     SELECT from_id as user_id FROM friends WHERE to_id = '100'
     UNION
     SELECT to_id as user_id FROM friends WHERE from_id = '100')               
ORDER  BY usertable.joining_date DESC
LIMIT  10  

2)使用SELECT usertable.name, usertable.user_id, usertable.image FROM `UserTable` AS usertable WHERE usertable.user_id <> '100' AND usertable.user_id NOT IN (SELECT from_id as user_id FROM friendrequests WHERE to_id = '100') AND usertable.user_id NOT IN (SELECT to_id as user_id FROM friendrequests WHERE from_id = '100') AND usertable.user_id NOT IN (SELECT from_id as user_id FROM friends WHERE to_id = '100') AND usertable.user_id NOT IN (SELECT to_id as user_id FROM friends WHERE from_id = '100') ORDER BY usertable.joining_date DESC LIMIT 10

我看到了this answer并尝试使用相同的逻辑:您在另一个表中添加了LEFT JOIN并添加了一个条件,即那些联接返回NULL值

LEFT JOIN

3)使用SELECT usertable.name, usertable.user_id, usertable.image FROM `UserTable` AS usertable LEFT JOIN friendrequests as FRa on FRa.from_id = usertable_user_id LEFT JOIN friendrequests as FRb on FRb.to_id = usertable_user_id LEFT JOIN friends as Fa on Fa.from_id = usertable_user_id LEFT JOIN friends as Fb on Fb.to_id = usertable_user_id WHERE usertable.user_id <> '100' AND FRa.from_id IS NULL AND FRb.to_id IS NULL AND Fa.from_id IS NULL AND Fb.to_id IS NULL

NOT EXISTS

对不起,但是没有示例数据或SQL Fiddle来测试那些查询,我无法告诉您它是否返回您想要的内容,或者它是否真的更快...


编辑:此页是从2009年开始的,因此自!我不会删除它,因为您仍然拥有我之前使用的查询结构:

我建议您查看此页面,以了解这些查询之间的区别,并给您一些实现所需内容的想法:https://explainextended.com/2009/09/18/not-in-vs-not-exists-vs-left-join-is-null-mysql/

此页中提出了第三种方法(使用SELECT usertable.name, usertable.user_id, usertable.image FROM `UserTable` AS usertable WHERE usertable.user_id <> '100' AND NOT EXISTS (SELECT from_id as user_id FROM friendrequests WHERE to_id = '100') AND NOT EXISTS (SELECT to_id as user_id FROM friendrequests WHERE from_id = '100') AND NOT EXISTS (SELECT from_id as user_id FROM friends WHERE to_id = '100') AND NOT EXISTS (SELECT to_id as user_id FROM friends WHERE from_id = '100') ORDER BY usertable.joining_date DESC LIMIT 10 ),但根据测试,这种方法效率不高:

  

但是,此查询的效率比前两个查询低一点:花费0.92 s。

     

这并不是性能下降太多,但是查询花费的时间增加了27%。