mySQL查询随机执行需要很长时间

时间:2016-10-24 03:15:07

标签: mysql database phpmyadmin database-performance

我是查询优化的新手,所以我阅读了很多文章并观看了YouTubes和其他内容,但我仍然无法弄明白。

问题是我想要为我的API执行此查询:

SELECT  req_id,follow_requests.insta_id as id,caption,follow_requests.male,
        users.name,users.profile_pic
    FROM  follow_requests
    INNER JOIN  users  ON follow_requests.insta_id = users.insta_id
    WHERE  (remaining_follow>0 && req_id<='574989')
      AND  NOT EXISTS
    (
        SELECT  *
            FROM  follows
            WHERE  follows.req_id=follow_requests.req_id
              AND  follows.follower_insta_id='3134816134'
    )
    ORDER BY  req_id DESC
    LIMIT  20

所以我记录了我的数据库并且摘要显示这个正在吃+ 42%的资源 这个查询的一些实例看起来像300秒,它平均有20秒!(他们在发送数据状态时遇到困难) 所以我试着更好地改变它(不是我真的知道我在做什么:) 我把它改成了这个

SELECT  fr.req_id, fr.insta_id as id, fr.caption, fr.male, u.name,
        u.profile_pic, fr.date, fr.remaining_follow
    FROM  follow_requests AS fr
    INNER JOIN  users AS u  ON fr.insta_id=u.insta_id
    WHERE  fr.remaining_follow>0
      AND  fr.insta_id!=3134816134
      AND  NOT EXISTS 
    (
        SELECT  *
            FROM  follows as f
            WHERE  f.req_id=fr.req_id
              AND  f.follower_insta_id='3134816134'
    )
    ORDER BY  fr.date DESC
    LIMIT  20
奇怪的是,前几次运行没问题!比如从0.1秒到0.7秒 在测试运行 但是在我伸展一下然后回来完成它之后,这也被卡住了+200,300秒,但是这次是排序状态 我用解释检查了查询,我注意到它没有使用日期索引! 如果我只从查询中删除'order by'部分,它变得非常快~0.2s

任何想法?

顺便说一句,几乎所有的列都被编入索引,并且跟随表有2M行,其他类似于+ 100k

抱歉如果我无法解释它或者我错过了给你一些重要信息,我只是新的;)

如果您能以某种方式解释新手可以理解的同时不会遗漏重要细节,我将非常感激:)

提前致谢

= - = - = - = - = - = - =更新1 = - = - = - = - = - = - =

感谢你的帮助,我现在达到了这个查询的时间效率,但是 我不得不改变整个事情,但它可能仍有问题

SELECT  follow_requests.req_id, follow_requests.insta_id as id,
        caption, follow_requests.male, users.name,users.profile_pic
    FROM  follow_requests
    INNER JOIN  users  ON follow_requests.insta_id = users.insta_id
    LEFT OUTER JOIN  follows  ON follows.req_id = follow_requests.req_id
      AND  follows.follower_insta_id = '3134816134'
    WHERE  follow_requests.remaining_follow >0
      AND  follow_requests.insta_id != 3134816134
      AND  (follows.follower_insta_id != 3134816134 || follows.follower_insta_id is null)
    ORDER BY  follow_requests.date DESC
    LIMIT  20
嗯,首先我需要说我没有写原始查询(第1个)而我自己并不了解所有这些:/但主程序员现在已经无法触及我必须取代他的位置或者整个项目将失败

关于问题是每个人都可以提交多个insta_id请求,但是应该只返回其中一个 主代码和@Kickstart代码(原始代码的优化版本,大约10秒的响应时间)是正确的(由于某种原因,我不明白 但我的代码返回相同insta_id的多个实例(使用不同的req_id)

还有一些机构可以告诉我为什么第一个查询做得那么糟糕?

4 个答案:

答案 0 :(得分:0)

我有两个解决方案

1ST:

而不是使用&#34;选择*&#34;使用&#34;选择id&#34;

SELECT fr.req_id, fr.insta_id as id, fr.caption, fr.male, u.name, u.profile_pic, fr.date, fr.remaining_follow
FROM follow_requests AS fr INNER JOIN users AS u 
ON fr.insta_id=u.insta_id
WHERE fr.remaining_follow>0 AND fr.insta_id!=3134816134 
    AND NOT EXISTS (SELECT f.id FROM follows as f WHERE f.req_id=fr.req_id AND f.follower_insta_id='3134816134')
ORDER BY fr.date DESC LIMIT 20

2ND:

你可以做到这一点

SELECT fr.req_id, 
       fr.insta_id AS id, 
       fr.caption, 
       fr.male, 
       u.name, 
       u.profile_pic, 
       fr.date, 
       fr.remaining_follow 
FROM   follow_requests AS fr 
       INNER JOIN users AS u 
               ON fr.insta_id = u.insta_id 
       INNER JOIN follows AS f 
              ON f.req_id = fr.req_id 
                 AND f.follower_insta_id != '3134816134' 
WHERE  fr.remaining_follow > 0 
       AND fr.insta_id != 3134816134
ORDER  BY fr.date DESC 
LIMIT  20 

答案 1 :(得分:0)

真的需要查看表声明和查询的EXPLAIN。

然而,可能值得尝试下表的LEFT OUTER JOIN,并检查不匹配(通过检查必须在该表上填充的列为NULL)。

但是,您在下表中有一个索引,它包含req_id和follower_insta_id字段吗?不是2个单独的索引,而是覆盖两个字段的索引。

SELECT req_id,
        follow_requests.insta_id as id,
        caption,
        follow_requests.male,
        users.name,users.profile_pic 
FROM follow_requests 
INNER JOIN users ON follow_requests.insta_id = users.insta_id 
LEFT OUTER JOIN follows ON follows.req_id = follow_requests.req_id AND follows.follower_insta_id = '3134816134'
WHERE follows.req_id IS NULL
AND remaining_follow > 0 
AND req_id <= '574989'
ORDER BY req_id DESC 
LIMIT 20

答案 2 :(得分:0)

解释@Kickstart代码

EXPLAIN SELECT follow_requests.req_id,
        follow_requests.insta_id as id,
        caption,
        follow_requests.male,
        users.name,users.profile_pic 
FROM follow_requests 
INNER JOIN users ON follow_requests.insta_id = users.insta_id 
LEFT OUTER JOIN follows ON follows.req_id = follow_requests.req_id AND follows.follower_insta_id = '3134816134'
WHERE remaining_follow > 0 
AND follow_requests.req_id <= '574989'
ORDER BY follow_requests.req_id DESC 
LIMIT 20


1   SIMPLE  follow_requests index   PRIMARY,insta_id,remaining_follow,remaining_follow...   PRIMARY 8       6812    Using where 
1   SIMPLE  follows ref follower_insta_id,req_id,follower_insta_id_req_id   follower_insta_id_req_id    17  insta_star.follow_requests.req_id,const 1   Using index 
1   SIMPLE  users   eq_ref  PRIMARY,insta_id    PRIMARY 8   insta_star.follow_requests.insta_id 1   

答案 3 :(得分:0)

对此有什么想法吗?

SELECT  lr.req_id, lr.insta_id AS id, u.name AS username, lr.media_id,
        lr.caption, lr.male
    FROM  like_requests AS lr use INDEX (remaining_like)
    INNER JOIN  users AS u  ON lr.insta_id=u.insta_id
    LEFT OUTER JOIN  likes AS l  ON l.req_id = lr.req_id
                                AND l.insta_id = 4021226743
    WHERE  lr.remaining_like>0
      AND  lr.req_id<459537
      AND  lr.insta_id!=4021226743
      AND  (l.insta_id!=4021226743 || l.insta_id is null)
      AND  lr.active=1
      AND  NOT EXISTS
    (
        SELECT  *
            FROM  like_reports
            WHERE  insta_id=4021226743
              AND  like_reports.req_id=lr.req_id
    )
    ORDER BY  lr.req_id DESC
    LIMIT  10

说明:

id, select_type, table, type, possible_keys, key, key_len, ref, rows, extra
------------------------------------------------------------------------
1   PRIMARY         lr              range   remaining_like                        remaining_like        4           NULL                            1056    Using index condition; Using where; Using filesort  
1   PRIMARY         l               ref     req_id,insta_id,req_id_insta_id       req_id_insta_id       16          insta_star.lr.req_id,const      1       Using where; Using index    
1   PRIMARY         u               eq_ref  PRIMARY,insta_id                      PRIMARY               8           insta_star.lr.insta_id          1       
2   MATERIALIZED    like_reports    ref     req_id,insta_id,insta_id_req_id       insta_id_req_id       8           const                           1       Using index 
哇,花了很多时间来调整它们?你们怎么出口到那些美丽的桌子形状?

=====更新=====

可能是因为大量用户使用API​​?现在它的夜晚我仍然有网上活跃用户我不知道也许-500(完全不知道) 但是每件事情都不顺利,没有挂起的查询过程? 我应该升级什么? 硬?内存 ?中央处理器? 我怎么知道其中一个是否缺乏?

=======更新2 ======

添加了表格结构

CREATE TABLE `like_requests` (
  `req_id` bigint(20) unsigned NOT NULL AUTO_INCREMENT,
  `insta_id` bigint(20) unsigned NOT NULL,
  `media_id` varchar(50) NOT NULL,
  `remaining_like` int(10) unsigned NOT NULL,
  `active` tinyint(10) NOT NULL DEFAULT '1',
  `count` int(10) unsigned NOT NULL,
  `date` timestamp NOT NULL DEFAULT CURRENT_TIMESTAMP,
  `caption` text CHARACTER SET utf8 COLLATE utf8_unicode_ci,
  `male` tinyint(4) DEFAULT NULL,
  PRIMARY KEY (`req_id`),
  KEY `insta_id` (`insta_id`),
  CONSTRAINT `like_requests_ibfk_1` FOREIGN KEY (`insta_id`) REFERENCES `users` (`insta_id`)

CREATE TABLE `likes` (
  `id` bigint(20) unsigned NOT NULL AUTO_INCREMENT,
  `insta_id` bigint(20) unsigned NOT NULL,
  `media_id` varchar(50) NOT NULL,
  `req_id` bigint(20) unsigned NOT NULL,
  `date` timestamp NULL DEFAULT CURRENT_TIMESTAMP,
  PRIMARY KEY (`id`),
  UNIQUE KEY `id` (`id`),
  KEY `req_id` (`req_id`),
  KEY `insta_id` (`insta_id`),
  CONSTRAINT `likes_ibfk_1` FOREIGN KEY (`req_id`) REFERENCES `like_requests` (`req_id`),
  CONSTRAINT `likes_ibfk_2` FOREIGN KEY (`insta_id`) REFERENCES `users` (`insta_id`)
) ENGINE=InnoDB AUTO_INCREMENT=7931674 DEFAULT CHARSET=latin1;

CREATE TABLE `users` (
  `insta_id` bigint(20) unsigned NOT NULL,
  `name` varchar(50) NOT NULL,
  `token` varchar(60) NOT NULL,
  `gem` int(10) NOT NULL DEFAULT '10',
  `coin` int(10) NOT NULL DEFAULT '10',
  `latitude` double DEFAULT NULL,
  `longitude` double DEFAULT NULL,
  `notif_token` varchar(50) DEFAULT NULL,
  `male` tinyint(1) DEFAULT NULL,
  `last_gotten_time` timestamp NOT NULL DEFAULT CURRENT_TIMESTAMP,
  `profile_pic` text,
  PRIMARY KEY (`insta_id`),
  UNIQUE KEY `insta_id` (`insta_id`)
) ENGINE=InnoDB DEFAULT CHARSET=latin1;