我正在使用MySQL在wiki上构建转发索引。我遇到了查询的性能问题,我希望能够帮助优化我的架构或查询
数据库大约1GB,有三个表
fi_keyword是一个包含70k关键字的表格
CREATE TABLE `fi_keyword` (
`id` int(11) NOT NULL AUTO_INCREMENT,
`keyword` varchar(100) NOT NULL,
PRIMARY KEY (`id`),
UNIQUE KEY `keyword` (`keyword`)
);
fi_titlekeywordlink是一个包含600万个条目,将关键字链接到维基页面的表格
CREATE TABLE `fi_titlekeywordlink` (
`id` int(11) NOT NULL AUTO_INCREMENT,
`keyword_id` int(11) NOT NULL,
`page_id` int(11) NOT NULL,
PRIMARY KEY (`id`),
KEY `fi_titlekeywordlink_a6434082` (`keyword_id`),
KEY `fi_titlekeywordlink_c2d3d2bb` (`page_id`),
CONSTRAINT `keyword_id_refs_id_67197756` FOREIGN KEY (`keyword_id`) REFERENCES `fi_keyword` (`id`),
CONSTRAINT `paper_id_refs_id_705ddf03` FOREIGN KEY (`page_id`) REFERENCES `fi_page` (`id`)
);
我正在将“搜索术语丰富”的搜索转换为SQL查询,例如
select p.*
from
fi_keyword as k0, fi_titlekeywordlink as l0,
fi_keyword as k1, fi_titlekeywordlink as l1,
fi_keyword as k2, fi_titlekeywordlink as l2,
fi_keyword as k3, fi_titlekeywordlink as l3,
fi_page as p
where
k0.keyword = e and k0.id = l0.keyword_id and p.id = l0.paper_id
and k1.keyword = 'search' and k1.id = l1.keyword_id and p.id = l1.paper_id
and k2.keyword = 'terms' and k2.id = l2.keyword_id and p.id = l2.paper_id
and k3.keyword = 'galore' and k3.id = l3.keyword_id and p.id = l3.paper_id
limit 1,10
然而,这需要大约半秒才能在我的MBP上运行。您是否有任何关于如何通过更改架构或查询来加速此类操作的建议?在这种情况下我不能使用单独的搜索服务器,正向索引必须在MySQL上运行。谢谢。
答案 0 :(得分:2)
以插入性能为代价,您可以从两个表中删除代理id
主键列,并在keyword
列上为fi_keyword和(keyword_id
创建主键索引, page_id
)作为fi_titlekeywordlink的主键索引。
如果您使用InnoDB,主键是聚簇索引,因此速度更快。
即使您没有进行此更改,fi_titlekeywordlink上的复合(多列)索引(keyword_id
,page_id
)也会提高效果,因为您将拥有覆盖索引( MySQL不必访问fi_titlekeywordlink上的表数据。这假设您的MySQL服务器有足够的RAM来容纳内存中的所有索引,并且您已经配置了MySQL服务器以允许它使用足够的RAM来实现它(配置变量在MyISAM和{{3之间不同}})。
有时,隐式JOIN对于MySQL来说可能过于复杂而无法正确优化。您还应该考虑使用JOIN
和ON
使用显式ANSI标准连接重写查询。
为简洁起见,您可能只是编写了SELECT p.*
,但请务必仅选择所需的列,以便您不会返回不需要的数据。只返回您需要的列可以减少工作量。
此外,LIMIT子句中的第一行为0,因此LIMIT 1, 10
会跳过第一行。使用LIMIT 0, 10
获取前10行。