以下是查询:
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.uid
中的每一行显示firstpoint_organisations.prid
和users
,即使某些用户没有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
然后在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)
答案 0 :(得分:1)
我会在u.status,u.uid上使用一个唯一索引,因为mysql必须使用fullscan来查看,我认为哪些条目的状态= 1。
我希望事后更快;)
答案 1 :(得分: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行以了解哪些行是第一行return - 该限制几乎没有影响,除了返回较少的行到客户端(较少的逗号IO)
我相信“代码越少越好”,所以从严格的风格角度来看,我已从您的查询中删除了非必要的代码:
OUTER
,因为没有其他类型的左连接