2015-05-23 63 views
0

玩一個mysql,想着如何解決未來的一件事。我想檢索我的朋友發佈的狀態(特定用戶ID)或發佈在我關注的組內。mysql解釋慢在左邊加入表

CREATE TABLE `status` (
    `id` int(11) NOT NULL AUTO_INCREMENT, 
    `user_id` int(11) NOT NULL, 
    `status` text COLLATE utf8_unicode_ci NOT NULL, 
    PRIMARY KEY (`id`), 
    KEY `IDX_F23501207E3C61F9` (`user_id`) 
) ENGINE=InnoDB AUTO_INCREMENT=1567559 DEFAULT CHARSET=utf8 COLLATE=utf8_unicode_ci 

CREATE TABLE `group_status` (
    `id` int(11) NOT NULL AUTO_INCREMENT, 
    `group_id` int(11) NOT NULL, 
    PRIMARY KEY (`id`), 
    KEY `IDX_F23501207E3C61F9` (`group_id`) 
) ENGINE=InnoDB AUTO_INCREMENT=1000001 DEFAULT CHARSET=utf8 COLLATE=utf8_unicode_ci 

我給這兩個表提供了1M行。

我正在查詢:

SELECT s.id, s.status, gs.group_id 
FROM status s 
LEFT JOIN group_status gs 
ON s.id = gs.id 
WHERE 
s.user_id IN (55883,122024,442468,846269,903941,980896,192660,20608,525056,563457) 
OR gs.group_id IN (78,79,79,80,80,83,84,85,86,87,88,89,89,91,92,92,94,98) 
ORDER BY s.id DESC 
LIMIT 15 

結果:

enter image description here

問題一:

不應該是這樣的額外的角色:「使用索引「而不是」在哪裏「?

問題二:

爲什麼響應時間這麼慢? 2,3s

enter image description here

編輯Tim的回答後:

enter image description here

  1. 使用工會沒有時,文件排序行爲我想是正常的嗎?
  2. 爲什麼在第二行解釋中使用'where'?如果第三個是'使用where,using index'?
  3. 如果從選擇中返回多少行,您認爲這會變慢?

union select似乎超快,但目前只有幾行返回每個選擇。我將嘗試在每個選擇中選擇更多的行。

+0

filesort可能是由狀態列引起的,該列被定義爲文本。 – Tim3880

+0

's.id = gs.id'讓我的大腦旋轉!爲什麼你有一個身份證號和身份證號;此外,爲什麼他們有相同的語義(因爲你加入他們)?? –

+0

裏克你的命名建議是什麼?你有什麼要問這個問題嗎? – EnchanterIO

回答

0

如果在不同列上有「OR」,mysql可能不會使用任何索引。

通常我們可以使用「UNION」兩個單獨的查詢來解決問題,每個查詢匹配一個條件。

SELECT id, status, group_id FROM 
(
    SELECT s.id, s.status, gs.group_id 
    FROM status s 
    LEFT JOIN group_status gs 
    ON s.id = gs.id 
    WHERE 
    s.user_id IN (55883,122024,442468,846269,903941,980896,192660,20608,525056,563457) 
UNION 
    SELECT s.id, s.status, gs.group_id 
    FROM status s 
    LEFT JOIN group_status gs 
    ON s.id = gs.id 
    WHERE 
    gs.group_id IN (78,79,79,80,80,83,84,85,86,87,88,89,89,91,92,92,94,98) 
) t 
ORDER BY id DESC 
LIMIT 15 

但是,在您的情況下,如果任一查詢返回大量記錄,這可能無效。

您的狀態列被定義爲文本,這可能會導致文件排序。你可以檢查它到一個長的varchar來看看這個文件是否可以運行。或者試試以避免更糟的情況:

SELECT ss.id, group_id, ss.status 
FROM (
SELECT id, group_id FROM 
(
    SELECT s.id, gs.group_id 
    FROM status s 
    LEFT JOIN group_status gs 
    ON s.id = gs.id 
    WHERE 
    s.user_id IN (55883,122024,442468,846269,903941,980896,192660,20608,525056,563457) 
UNION 
    SELECT s.id, gs.group_id 
    FROM status s 
    LEFT JOIN group_status gs 
    ON s.id = gs.id 
    WHERE 
    gs.group_id IN (78,79,79,80,80,83,84,85,86,87,88,89,89,91,92,92,94,98) 
) t 
ORDER BY id DESC 
LIMIT 15 
) f 
JOIN status ss 
ON f.id =ss.id 
ORDER BY ss.id 
+0

Thx置評。我編輯了我的答案並提供了更多詳細信息,問題 – EnchanterIO

+0

在大多數情況下,您應該對這種查詢使用union。當查詢返回非常大的百分比(50%等)時它會變慢,並且返回很多列,尤其是blob字段。 – Tim3880

+0

我將「文本」更改爲「varchar(20000)」,但是相同。嗯,我不確定你在第二個例子中想要達到什麼目的?你能透露你的想法嗎? – EnchanterIO