[英]How can I improve the speed of this MySQL query?
這是查詢:
SELECT
u.uid as UID,
fuo.uid as FUO_UID,
fo.prid as FO_NAME
FROM
users u
LEFT OUTER JOIN firstpoint_users_organisations fuo ON (u.uid=fuo.uid)
LEFT OUTER JOIN firstpoint_organisations fo ON (fo.nid=fuo.nid)
WHERE
u.status=1 AND u.uid>1
ORDER BY u.uid
LIMIT 3;
表格:
users
+------------------+------------------+------+-----+---------+----------------+
| Field | Type | Null | Key | Default | Extra |
+------------------+------------------+------+-----+---------+----------------+
| uid | int(10) unsigned | NO | PRI | NULL | auto_increment |
| name | varchar(60) | NO | UNI | | |
| status | tinyint(4) | NO | | 0 | |
+-----------------------------------------------------------------------------+
firstpoint_users_organisations
+-------+------------------+------+-----+---------+-------+
| Field | Type | Null | Key | Default | Extra |
+-------+------------------+------+-----+---------+-------+
| nid | int(10) unsigned | NO | PRI | 0 | |
| uid | int(10) unsigned | NO | PRI | 0 | |
+-------+------------------+------+-----+---------+-------+
firstpoint_organisations
+----------+------------------+------+-----+---------+-------+
| Field | Type | Null | Key | Default | Extra |
+----------+------------------+------+-----+---------+-------+
| nid | int(10) unsigned | NO | PRI | 0 | |
| prid | varchar(32) | NO | | | |
+------------------------------------------------------------+
我希望為users
每一行顯示users.uid
和firstpoint_organisations.prid
,即使某些用戶沒有prid
,在這種情況下我顯示NULL(因此左外連接)。 連接應如下:
users
uid - firstpoint_users_organisations
\---->uid
nid - firstpoint_organisations
\-------->nid
prid
因此,每個用戶(用戶)都有一個用戶ID(uid),並且他們與之關聯的組織(firstpoint_users_organisation)具有節點ID(nid)並存儲該關聯。 然后,組織的詳細信息將存儲在firstpoint_organisations中。
因此每個用戶都有一個prid
,但如果他們沒有,則顯示NULL。
現在,如果我在firstpoint_users_organisations
上執行INNER JOIN,然后在firstpoint_organisations
上執行INNER JOIN,我會獲得良好的查詢速度(上述查詢在0.02秒內運行)。 但是,當我切換到LEFT OUTER JOIN,所以我可以獲得所有用戶, prid
或沒有prid
,上面的查詢需要大約90秒才能運行。
有什么辦法可以加快查詢速度嗎? 有約。 users
表中有70,000行,但即使使用LIMIT 3,使INNER JOIN成為LEFT OUTER JOIN需要花費大量時間。 有趣的是,查詢需要花費相同的時間來運行LIMIT 30,所以我認為我的查詢存在根本性的錯誤。
按要求說明:
+----+-------------+-------+--------+---------------+---------+---------+-----------------------+-------+----------------------------------------------+
| id | select_type | table | type | possible_keys | key | key_len | ref | rows | Extra |
+----+-------------+-------+--------+---------------+---------+---------+-----------------------+-------+----------------------------------------------+
| 1 | SIMPLE | u | range | PRIMARY | PRIMARY | 4 | NULL | 13152 | Using where; Using temporary; Using filesort |
| 1 | SIMPLE | fuo | index | NULL | PRIMARY | 8 | NULL | 3745 | Using index |
| 1 | SIMPLE | fo | eq_ref | PRIMARY | PRIMARY | 4 | dbdb-dbdb_uat.fuo.nid | 1 | |
+----+-------------+-------+--------+---------------+---------+---------+-----------------------+-------+----------------------------------------------+
3 rows in set (0.00 sec)
我會在u.status,u.uid上使用一個唯一的索引,因為mysql必須使用fullscan來查看,我認為哪些條目的狀態= 1。
我希望事后更快;)
您的查詢是無意義的(因為uid > 1
將包括除一個用戶之外的所有用戶)使用uid上的索引,因此對該索引使用IGNORE INDEX提示:
SELECT
u.uid as UID,
fuo.uid as FUO_UID,
fo.prid as FO_NAME
FROM users u IGNORE INDEX (uid)
LEFT JOIN firstpoint_users_organisations fuo ON u.uid=fuo.uid
LEFT JOIN firstpoint_organisations fo ON fo.nid=fuo.nid
WHERE u.status=1
AND u.uid > 1
ORDER BY u.uid
LIMIT 3
您應該在users(status)
上放置索引,如果有足夠的行狀態,則可能會給您帶來一些好處!= 1
非常期望更改LIMIT沒有任何效果,因為在應用限制之前必須對70000行進行排序,以確定哪些行是要返回的第一行 - 該限制幾乎沒有效果,除了將更少的行返回給客戶端(少逗號IO)
我相信“代碼越少越好”,所以從嚴格的風格角度來看,我已從您的查詢中刪除了非必要的代碼:
OUTER
因為沒有其他類型的左連接
聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.