我有两个非常大的表(第一个表是5 mio。条目,第二个表也是那么多行。)
第一个表objects
有一个主键objectID
我的第二个表search
有一个列searchID
和一个列objectID
,它引用了对象表中的objectID。
我现在想要的是,从我的对象表中获取所有对象,其中objectID在searchID = 1的搜索表中 searchID 1的行数非常大 - 大约有200万个条目。 我使用searchID / objectID组合的唯一键索引表。 查询如下所示:
SELECT *
FROM objects
JOIN search
ON search.searchID = 1
AND objects.objectID = search.objectID
此查询运行得非常快。 但只要我不在ORDER BY
或对象表格中的name
添加title
子句。
似乎任何指数都无济于事。
这个问题是否无法通过索引解决?我需要什么指数?
编辑:表格请求
TABLE `objects` (
`objectID` int(11) NOT NULL AUTO_INCREMENT,
`name` varchar(255) NOT NULL,
`title` varchar(255) NOT NULL,
PRIMARY KEY (`objectID`),
KEY `name` (`name`),
KEY `title` (`title`)
) ENGINE=InnoDB DEFAULT CHARSET=utf8
TABLE `search` (
`searchID` int(11) NOT NULL,
`objectID` int(11) NOT NULL,
UNIQUE KEY `searchID` (`searchID`,`objectID`)
) ENGINE=InnoDB
使用ORDER BY EXPLAIN :
id select_type table type possible_keys key key_len ref rows Extra
1 SIMPLE search ref searchID,objectID searchID 4 const 1014549 Using index; Using temporary; Using filesort
1 SIMPLE objects eq_ref PRIMARY PRIMARY 4 db_test.search.objectID 1 Using index
没有ORDER BY的EXPLAIN :
id select_type table type possible_keys key key_len ref rows Extra
1 SIMPLE search ref searchID,contactID searchID 4 const 1014549 Using index
1 SIMPLE contact eq_ref PRIMARY PRIMARY 4 db_test.search.objectID 1 Using index
答案 0 :(得分:0)
首先你的查询不是很正确,正确的版本应该是:
SELECT *
FROM objects
INNER JOIN search
ON (objects.objectID = search.objectID and search.searchID = 1)
另一个版本:
SELECT *
FROM objects
where objects.objectID in (
select search.objectID from search where search.searchID = 1)
从逻辑的角度来看,它们完全相同,但我不确定mysql是否会以相同的方式执行它们,所以测试两者并选择最快的一个
关于索引的下一期:
sort_buffer_size
和join_buffer_size
现在您可以将查询更改为其中一个(测试两者以选择最快)
SELECT *
FROM objects use index (INDEXNAME)
INNER JOIN search
ON (objects.objectID = search.objectID and search.searchID = 1)
order by SORTCOLUMN
或
SELECT *
FROM objects use index (INDEXNAME)
where objects.objectID in (
select search.objectID from search where search.searchID = 1)
order by SORTCOLUMN
这就是我在测试数据库上得到的结果(解释扩展对于两个查询都是相同的):
id type table type pk key key_len ref rows filter Extra
1 SIMPLE objects index srtcol 142 2091427 100.00 Using index
1 SIMPLE search eq_ref sid sid 5 const,testhash.objects.objectID 1 100.00 Using index
注意:如果你需要这么长的字符串(varchar 255) - 你可以制作一个技巧:添加整数列,根据正确的顺序设置它的值,并对此列进行排序和索引
这是我要测试的表格:
CREATE TABLE `objects` (
`objectID` int(10) unsigned NOT NULL AUTO_INCREMENT,
`sortcol` varchar(45) DEFAULT NULL,
PRIMARY KEY (`objectID`),
UNIQUE KEY `srtcol` (`sortcol`,`objectID`)
) ENGINE=InnoDB AUTO_INCREMENT=2490316 DEFAULT CHARSET=utf8;
CREATE TABLE `search` (
`id` int(10) unsigned NOT NULL AUTO_INCREMENT,
`searchID` int(10) unsigned NOT NULL,
`objectID` int(10) unsigned NOT NULL,
PRIMARY KEY (`id`),
UNIQUE KEY `sid` (`searchID`,`objectID`)
) ENGINE=InnoDB AUTO_INCREMENT=2162656 DEFAULT CHARSET=utf8;
每个都有大约2米的随机行