2016-10-24 144 views
0

我是新來的查詢優化,所以我看了很多文章,看了YouTubes和東西,但我仍然無法弄清楚。mySQL查詢隨機需要很長時間來執行

的事情是我有這個疑問,我要執行我的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.7s 在測試運行 但我去拉伸了一下,並回來完成它,這也被卡住了+200,300秒,但在排序狀態這一次 我檢查查詢與解釋,我注意到它不使用日期索引! 如果我只是刪除'由'部分查詢它變得真的很快〜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),我不明白所有它自己:/但主程序員現在是不可及的,我必須佔據他的位置或整個項目將失敗

about問題是每個人都可以提交一個insta_id的多個請求,但應該只返回其中的一個 主要代碼和@Kickstart代碼(這是優化版本的原始一個與大約10秒響應時間)是否正確(由於某種原因,我不明白 但我的代碼返回多個insta_id實例(不同req_id)

並且alsocould一些身體啓發我爲什麼第一個查詢做得這麼差?

+0

您的查詢缺少_follows.req_id IS NULL_檢查,這是非常重要的。 LEFT OUTER JOIN將嘗試進行連接,但即使未找到匹配項,仍會返回一行,並將不匹配的表中的列設置爲NULL。因此,如果你做了一個LEFT OUTER JOIN,那麼檢查一個必須在那裏的列是NULL,然後你從第一個表中返回沒有第二個表上匹配的行。 – Kickstart

+0

@Kickstart是的,我故意這樣做,我的意思是這兩個表的作品是這樣的,用戶1在follow_request中提交他的請求,用戶2可以做到這一點,用戶操作在後面提交,用戶2不應該看到,用戶再次請求(只能爲每個用戶完成一次),所以爲什麼我保持爲空意味着它不會顯示任何用戶已經完成至少一次的請求,但我需要向其他用戶顯示或他們永遠不會完成,但我不是100%確定,如果我說的是正確的或不); –

+0

'後續'有'INDEX(follower_insta_id,req_id)'? –

回答

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 
+1

非常感謝很多人,你的要求做了17秒,仍然很高,但重要的部分是它激發了我如何寫一個更好的查詢,它的時間是優化的,但有些東西仍然是錯誤的,我在路上,但我會在~20分鐘內添加一個答案,並在那裏解釋更多,請看看它然後 –

+0

@question更新?我是否也應該添加表結構和解釋? 和您的查詢得到更快的限制,我的意思是限制100比限制20快,限制100搜索差不多一半作爲限制20,說解釋,爲什麼? –

+0

我無法對此表示感謝,日誌顯示此查詢工作就像+1800次!現在更好:),但我在哪裏可以學習如此查詢?任何良好的YouTube頻道?有用的鏈接? –

0

我得到了2個解決方案

月1日:

而不是使用 「SELECT *」 使用 「選擇ID」

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 
+0

感謝您的回覆,第一個卡住了起始狀態,第二個返回重複行 –

+0

開始一個新問題;一定要包含「SHOW CREATE TABLE」和它正在嘗試查找的解釋。 –

+0

@SeyedMansourMirbehbahani你如何通過刪除重複刪除 – Beginner

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 
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; 
+0

'SHOW CREATE TABLE',please。 –

+0

'SHOW CREATE VIEW'也是。看起來你有一個視圖? –

+0

嘗試不使用VIEW,而是使用等效的SELECT代替。 –