[英]MySql: joining same table with millions rows
我有一個包含數百萬行的表(SF_COLLECTIONS)
ID MEMBERID COLLECTIONID CARDID STATE (D / M)
1 1 1 1 D
2 1 1 2 D
3 2 1 1 M
4 2 1 2 M
5 2 1 3 D
6 1 1 3 M
我必須將那些 MEMBERID = 1 和 STATE = D 與那些 MEMBERID = 2 和 STATE = M 交叉,反之亦然
這是我的查詢
SELECT 1
FROM sf_collections AS rac
INNER JOIN sf_collections AS myrac
ON
(myrac.cardid = rac.cardid AND
(
(myrac.state = "M" AND rac.state = "D") OR
(myrac.state = "D" AND rac.state = "M")
)
)
WHERE
rac.memberid = 1 AND myrac.memberid = 2
GROUP BY rac.memberid
(響應時間約 4 秒)
這是一種有效的方法還是有更好的方法來提高性能?
樣本數據集:
CREATE TABLE `sf_collections` (
`id` int(11) NOT NULL auto_increment,
`memberid` int(11) NOT NULL,
`collectionid` int(11) NOT NULL,
`cardid` int(11) NOT NULL,
`state` varchar(1) NOT NULL,
PRIMARY KEY (`id`),
UNIQUE KEY `sf_collections_pkey` (`memberid`,`collectionid`,`cardid`,`state`),
KEY `collectionid` (`collectionid`),
KEY `memberid` (`memberid`),
KEY `cardid` (`cardid`),
KEY `state` (`state`)
) ENGINE=MyISAM AUTO_INCREMENT=22627806 DEFAULT CHARSET=latin1
INSERT INTO sf_collections (memberid,collectionid,cardid,state) VALUES
(1,1,1,'D'),
(1,1,2,'D'),
(1,1,3,'M'),
(2,1,1,'M'),
(2,1,2,'M'),
(2,1,3,'D');
SELECT 1
FROM sf_collections AS rac
INNER JOIN sf_collections AS myrac
ON
(myrac.cardid = rac.cardid AND
(
(myrac.state = "M" AND rac.state = "D") OR
(myrac.state = "D" AND rac.state = "M")
)
)
WHERE
rac.memberid = 1 AND myrac.memberid = 2
GROUP BY rac.memberid
謝謝
編輯:MySql 是 5.0(很舊,無法升級)
將INDEX(cardid)
替換為 INDEX INDEX(cardid, state)
如果可行,不要同時檢查 D->M 和 M->D; 只做一個方向。 這將減少一半的努力。
避免SELECT... GROUP BY...
通過切換到EXISTS ( SELECT 1... )
。 如果有多個匹配的行,這將加快速度。 如果您最終要“列出匹配項”,我們不妨看看您想要什么,而不是挑剔GROUP BY
的不當使用。 你會使用GROUP_CONCAT
嗎?
從 MyISAM 遷移到 InnoDB。 即使在 5.0 中,這個查詢本質上也可能更快。
DROP INDEX(memberid)
因為唯一索引處理此類。
你有什么需要id
嗎? 如果不是,請擺脫它並將 4 列UNIQUE
索引提升為PRIMARY KEY
。
如果state
只是一個標志 (0/1),則可能永遠不會使用INDEX(state)
; 算了吧。
聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.