2017-07-13 61 views
-1

我們有這樣的用戶表 - 擁有超過2000萬個條目。MySQL查詢建議 - 列與聯合

CREATE TABLE `users` (
    `uid` int(10) unsigned NOT NULL AUTO_INCREMENT, 
    `name` varchar(64) default '', 
    `email` varchar(64) default '', 
    `flag` int(10) unsigned DEFAULT '0', 
    PRIMARY KEY (`uid') 
) ENGINE=InnoDB DEFAULT CHARSET=utf8; 

在我們的管理面板中,我們希望顯示一些固定用戶和來自用戶表的搜索結果。

有我們想象的展現銷固用戶(請建議如果任何其他更好的方法)

1)在用戶表中添加一個單獨列固定用戶的兩種方法。然而,與用戶總數(> 20M)相比,固定用戶數量很少(少於100個)。因此,這種方法似乎並不樂觀。

2)固定用戶和使用加入的一個單獨的表,

CREATE TABLE `pinnedusers` (
    `uid` int(10) unsigned NOT NULL default 0, 
    PRIMARY KEY (`uid`), 
) ENGINE=InnoDB DEFAULT CHARSET=utf8; 

和運行加入,例如,

select * 
from users 
left join pinnedusers 
    on pinnedusers.uid=users.uid 
order by pinnedusers.uid desc 
limit 200; 

然而,我們所擔心的第二個方法的性能因爲它涉及加入,訂購,限制。

你有什麼建議?

+1

第二種方法。 – Strawberry

+0

'flag'確定用戶是否被固定?如果沒有,則有一個「固定位」字段並對其進行索引或使用第二種方法。使用pinnedusers表作爲基礎表,儘管使用內部連接。 –

+0

應該__oin_而不是_joint_。第二種方法是首選的方法,只要索引了適當的列,性能就不成問題。我將使用pinnedusers作爲from表,並且將join(不是左連接)加入到users表中。 –

回答

0

這應該產生你想要的結果,並指出哪些行是「固定」用戶。

SELECT 
    a.*, 
    IF(b.`id` IS NULL,0,1) as `is_pinned` 
FROM users a 
LEFT JOIN pinnedusers b 
    on b.uid = a.uid 
ORDER BY IF(b.`id` IS NULL,0,1) DESC, a.uid DESC 
LIMIT 200; 
0

這不是JOIN害怕,它是掃描整個20M行的需要。

「顯示了幾個固定用戶」,用這個「顯示多達200個固定用戶」:

SELECT u.* 
    FROM pinnedusers p 
    JOIN users u USING(uid) 
    ORDER BY ... 
    LIMIT 200; 

如果有200個多家固定用戶較少,名單將有小於200元。但該查詢將會很快。

你原來的查詢和斯隆的速度都非常慢,因爲它們將不得不掃描整個20M行(假設少於200個被固定)。

如果你想要所有的固定用戶,足夠的非固定用戶填寫200個列表,那是一個不同的任務。但是,哪個非固定用戶你喜歡?前幾個?那會很快。一個隨機數?這更復雜,否則它也會掃描整個20M。其他一些標準?