比如使用MySQL,如果movies
表有20,000条记录,并且每条记录都有一个字段,即电影的描述,最长可达2k字节。我们如何在描述中搜索带有“自然”一词的电影?如果可能的话,它会很快,而不是通过所有20,000条记录。 (如果在某些其他情况下,例如书籍,n
可以是200,000或更多)。
答案 0 :(得分:4)
我不会直接处理描述列 - 选择的每行函数很少能很好地扩展。我订阅的一个指导原则是永远不必处理 列中的内容(如您的情况中的描述,或逗号分隔变量列的部分或甚至名称(第一个/最后一个)和地址(街道/镇/州)组件)。如果你这样做,通常会有一种更有效的方式。
我要做的是在表上插入,更新和删除触发器。对于插入/更新触发器,我将沿着DescLookup
下面的行填充另一个表:
Movies:
Id primary key
Title
Description
DescLookup:
Word
MovieId foreign key Movies(Id)
Count
primary key (Word,MovieId)
index (MovieId)
基本上,对于描述中的每个非噪音词(例如,对and
,or
,by
,标点符号,单字母词等等进行折扣,您在此表中输入一个条目(使用较低的单词)。
确保触发器在重新填充之前删除该MovieId
的所有当前行,以免留下不正确的信息。
然后使用该表运行查询。这将查找单词的“成本”移动到插入/更新而不是每个选择,从而大大降低了成本。这很有效,因为浩大的大多数数据库的读取频率远高于写入数据库,因此将成本转移到写入部分是一个好主意。
请记住,这需要额外的存储空间,但如果你检查了人们对数据库提出的大量问题,“我怎么能快速完成这个?”远远超过“我如何使用更少的磁盘空间?”。
删除触发器只会删除DescLookup
表中与相关MovieId
相关的所有条目。
因为Word
列已被编入索引(并且,根据您的要求,您将不搜索每个描述字段),对其进行搜索将非常快。那是因为:
select MovieId from DescLookup where Word = 'nature';
会打击:
select Id from Movies where lower(Description) like '%nature%';
离开水面。
答案 1 :(得分:2)
在这种情况下,您希望使用全文搜索索引。请注意,虽然有一些捕获量,例如最小字数,长度,停用词等。
FTS的语法如下所示:
WHERE MATCH (field) AGAINST ('text');