我有两张桌子。一个是User表,在userid上有一个主键,另一个表用外键引用用户表。
User表只有一个条目(现在),另一个表有一百万个。
以下联接让我很生气:
SELECT p0_.*, p1_.*
FROM photo p0_, User p1_
WHERE p0_.user_id = p1_.user_id
ORDER BY p0_.uploaddate DESC Limit 10 OFFSET 100000
查询在非常快的机器上需要12秒,订购时间为0.0005秒而没有订单。
我在user_id和uploaddate上有user_id(IDX_14B78418A76ED395)和复合索引(“search2”)的索引。
EXPLAIN显示以下内容:
+----+-------------+-------+------+------------------------------+----------------------+---------+---------------------+-------+---------------------------------+
| id | select_type | table | type | possible_keys | key | key_len | ref | rows | Extra |
+----+-------------+-------+------+------------------------------+----------------------+---------+---------------------+-------+---------------------------------+
| 1 | SIMPLE | p1_ | ALL | PRIMARY | NULL | NULL | NULL | 1 | Using temporary; Using filesort |
| 1 | SIMPLE | p0_ | ref | IDX_14B78418A76ED395,search2 | IDX_14B78418A76ED395 | 4 | odsfoto.p1_.user_id | 58520 | |
+----+-------------+-------+------+------------------------------+----------------------+---------+---------------------+-------+---------------------------------+
表定义:
CREATE TABLE `photo` (
`id` int(11) NOT NULL AUTO_INCREMENT,
`user_id` int(11) NOT NULL,
`album_id` int(11) DEFAULT NULL,
`exif_id` int(11) DEFAULT NULL,
`title` varchar(50) COLLATE utf8_unicode_ci NOT NULL,
`width` int(11) NOT NULL,
`height` int(11) NOT NULL,
`uploaddate` datetime NOT NULL,
`filesize` int(11) DEFAULT NULL,
`path` varchar(200) COLLATE utf8_unicode_ci NOT NULL,
`originalFilename` varchar(200) COLLATE utf8_unicode_ci NOT NULL,
`mimeType` varchar(200) COLLATE utf8_unicode_ci NOT NULL,
`description` longtext COLLATE utf8_unicode_ci,
`gpsData_id` int(11) DEFAULT NULL,
`views` int(11) DEFAULT NULL,
`likes` int(11) DEFAULT NULL,
PRIMARY KEY (`id`),
UNIQUE KEY `UNIQ_14B78418B0FC9251` (`exif_id`),
UNIQUE KEY `UNIQ_14B7841867E96507` (`gpsData_id`),
KEY `IDX_14B78418A76ED395` (`user_id`),
KEY `IDX_14B784181137ABCF` (`album_id`),
KEY `search_idx` (`uploaddate`),
KEY `search2` (`user_id`,`uploaddate`),
KEY `search3` (`uploaddate`,`user_id`)
) ENGINE=InnoDB DEFAULT CHARSET=utf8 COLLATE=utf8_unicode_ci;
CREATE TABLE `user` (
`user_id` int(11) NOT NULL,
`photoCount` int(11) NOT NULL,
`photoViews` int(11) NOT NULL,
`photoComments` int(11) NOT NULL,
`photoLikes` int(11) NOT NULL,
`username` varchar(255) COLLATE utf8_unicode_ci NOT NULL,
PRIMARY KEY (`user_id`)
) ENGINE=InnoDB DEFAULT CHARSET=utf8 COLLATE=utf8_unicode_ci;
我该怎么做才能加快这个问题?
答案 0 :(得分:25)
看起来你的MySQL无法进行后期行查找:
试试这个:
SELECT p.*, u.*
FROM (
SELECT id
FROM photo
ORDER BY
uploaddate DESC, id DESC
LIMIT 10
OFFSET 100000
) pi
JOIN photo p
ON p.id = pi.id
JOIN user u
ON u.user_id = p.user_id
答案 1 :(得分:1)
您需要uploaddate
上的单独索引。仅当uploaddate
是其中的第一列时,此排序才会利用复合索引。
您还可以尝试将user_id添加到ORDER BY:
....
ORDER BY p0_.user_id, p0_.uploaddate
答案 2 :(得分:1)
你有两个问题:
您需要创建一个INDEX(user_id, uploaddate)
,这将大大提高查询效率。
您需要找到使用LIMIT 10 OFFSET 100000
的变通方法。 MySQL正在创建一个包含100,000条记录的记录集,然后它将最后10条记录拉到最后......这是非常低效的。
http://www.mysqlperformanceblog.com/2006/09/01/order-by-limit-performance-optimization/讨论了大限制/偏移问题。
答案 3 :(得分:0)
首先尝试基于主键获取结果而不使用连接并使用结果再次查询结果 例如:
$ userIds = mysql :: select("从照片中选择user_id ORDER BY p0_.uploaddate DESC Limit 10 OFFSET 100000");
$ photoData = mysql :: select(" SELECT p0 _。,p1 _。 FROM photo p0_,用户p1_ 在p0_.uploaddate")中按顺序排列p0_.user_id = p1_.user_id和p0_.user_id($ userIds-> user_id);
在这里,我们将声明分为两部分:
1.我们可以根据主键轻松订购和获取,也没有连接
2.基于id和order by获取查询结果仅在有限的列上,我们可以在更短的时间内检索数据
答案 4 :(得分:-1)
使用Quassnoi回答,从30秒到0.015秒/0.000秒! 这就是我所谓的MySql专业知识! 我从我的个人项目中剪下了一个Join(不与自己联接)
Select ser.id_table, ser.id_rec, ser.relevance, cnt, title, description, sell_url, medium_thumb,
unique_id_supplier, keywords width, height, media_type
from (
Select ser.id_rec, ser.id_table, ser.relevance, ser.cnt
from searchEngineResults ser
where thisSearch = 16287
order by ser.relevance desc, cnt desc, id_rec
) ser
join photo_resell sou on sou.id = ser.id_rec
#join searchEngineResults ser on ser.id_rec = tmp.id_rec
limit 0, 9