我有以下SQL查询:
SELECT
upd.*,
usr.username AS `username`,
usr.profile_picture AS `profile_picture`
FROM
updates AS upd
LEFT JOIN
subscribers AS sub ON upd.uid=sub.suid
LEFT JOIN
users AS usr ON upd.uid=usr.uid
WHERE
upd.deleted='0' && (upd.uid='118697835834' || sub.uid='118697835834')
GROUP BY upd.id
ORDER BY upd.date DESC
LIMIT 0, 15
我获得所有用户(118697835834)更新,他使用左连接的另一个表中的个人资料图片以及他所有的订阅用户更新,所以我可以在他的新闻源中显示它们。
然而,随着更新越来越多,所以查询需要更多时间加载...现在使用Codeigniter的Profiler我可以看到查询需要 1.3793 ...
现在我已经创建了大约18k个虚拟账户并订阅了我,反之亦然,所以我可以测试执行时间...考虑到我在本地主机,我得到的时间很悲惨......
我也有一些索引,我想在users表中需要更多(username和uid作为唯一),更新表(update_id为唯一,uid为索引)
我想我做错了会得到如此糟糕的结果......
修改: 运行EXPLAIN EXTENDED结果:
Array
(
[0] => stdClass Object
(
[id] => 1
[select_type] => SIMPLE
[table] => upd
[type] => ALL
[possible_keys] => i2
[key] =>
[key_len] =>
[ref] =>
[rows] => 22
[filtered] => 100.00
[Extra] => Using where; Using temporary; Using filesort
)
[1] => stdClass Object
(
[id] => 1
[select_type] => SIMPLE
[table] => sub
[type] => ALL
[possible_keys] =>
[key] =>
[key_len] =>
[ref] =>
[rows] => 18244
[filtered] => 100.00
[Extra] => Using where
)
[2] => stdClass Object
(
[id] => 1
[select_type] => SIMPLE
[table] => usr
[type] => eq_ref
[possible_keys] => uid
[key] => uid
[key_len] => 8
[ref] => site.upd.uid
[rows] => 1
[filtered] => 100.00
[Extra] =>
)
)
EDIT2:显示表格 用户表:
CREATE TABLE `users` (
`id` bigint(20) NOT NULL AUTO_INCREMENT,
`uid` bigint(20) NOT NULL,
`username` varchar(20) COLLATE utf8_unicode_ci NOT NULL,
`email` text CHARACTER SET latin1 NOT NULL,
`password` text CHARACTER SET latin1 NOT NULL,
`profile_picture_full` text COLLATE utf8_unicode_ci NOT NULL,
`profile_picture` text COLLATE utf8_unicode_ci NOT NULL,
`date_registered` datetime NOT NULL,
`activated` tinyint(1) NOT NULL,
`closed` tinyint(1) NOT NULL,
PRIMARY KEY (`id`),
UNIQUE KEY `uid` (`uid`),
UNIQUE KEY `username` (`username`)
) ENGINE=MyISAM AUTO_INCREMENT=23521 DEFAULT CHARSET=utf8 COLLATE=utf8_unicode_ci
订阅者表:
CREATE TABLE `subscribers` (
`id` bigint(20) NOT NULL AUTO_INCREMENT,
`sid` bigint(20) NOT NULL,
`uid` bigint(20) NOT NULL,
`suid` bigint(20) NOT NULL,
`date` datetime NOT NULL,
PRIMARY KEY (`id`)
) ENGINE=MyISAM AUTO_INCREMENT=18255 DEFAULT CHARSET=utf8 COLLATE=utf8_unicode_ci
更新表:
CREATE TABLE `updates` (
`id` int(11) NOT NULL AUTO_INCREMENT,
`update_id` bigint(19) NOT NULL,
`uid` bigint(20) NOT NULL,
`type` text COLLATE utf8_unicode_ci NOT NULL,
`update` text COLLATE utf8_unicode_ci NOT NULL,
`date` datetime NOT NULL,
`total_likes` int(11) NOT NULL,
`total_comments` int(11) NOT NULL,
`total_favorites` int(11) NOT NULL,
`category` bigint(20) NOT NULL,
`deleted` tinyint(1) NOT NULL,
`deleted_date` datetime NOT NULL,
PRIMARY KEY (`id`),
UNIQUE KEY `i1` (`update_id`),
KEY `i2` (`uid`),
KEY `deleted_index` (`deleted`)
) ENGINE=MyISAM AUTO_INCREMENT=23 DEFAULT CHARSET=utf8 COLLATE=utf8_unicode_ci
答案 0 :(得分:2)
试试这个(没有GROUP BY
):
SELECT
upd.*,
usr.username AS `username`,
usr.profile_picture AS `profile_picture`
FROM
updates AS upd
LEFT JOIN
users AS usr
ON upd.uid = usr.uid
WHERE
upd.deleted='0'
AND
( upd.uid='118697835834'
OR EXISTS
( SELECT *
FROM subscribers AS sub
WHERE upd.uid = sub.suid
AND sub.uid = '118697835834'
)
)
ORDER BY upd.date DESC
LIMIT 0, 15
至少应将联接中使用的列编入索引:updates.uid
,users.uid
和subscribers.suid
。
我还会在subscribers.uid
添加一个索引。
答案 1 :(得分:1)
尝试:
SELECT
upd.*,
usr.username AS `username`,
usr.profile_picture AS `profile_picture`
FROM
updates AS upd
LEFT JOIN
subscribers AS sub ON upd.uid=sub.suid
LEFT JOIN
users AS usr ON upd.uid=usr.uid
WHERE
upd.deleted=0 and upd.uid in (118697835834,118697835834)
GROUP BY upd.id
ORDER BY upd.date DESC
LIMIT 0, 15
请注意,'
已从数值中删除,而按位运算符已更改为常规运算符。
答案 2 :(得分:1)
不要使用连接,试试这个:
select *,
(select username from users where uid = upd.uid) as username,
(select profile_picture from users where uid = upd.uid) as profile_picture,
from updates as upd
WHERE
upd.deleted='0' && upd.uid='118697835834'
(未经测试!)
也许您必须检查where子句中是否存在具有另一个子选择的订户。
另一种方法是在子选择上而不是在整个表上进行连接。这也可能会提高您的表现。
答案 3 :(得分:0)
不应该花太长时间跑;你有'已删除'的索引吗?什么是'GROUP BY id'在做什么?它应该是UID吗?它可以出来,如果ID实际上只是一个自动增量,唯一的ID? (这既昂贵又毫无意义)
答案 4 :(得分:0)
我认为你最好将这个查询分成用户表中的select,然后将这些结果与subscriber表上的select结合起来。