《基于 Mysql 实现一个简易版搜索引擎.docx》由会员分享,可在线阅读,更多相关《基于 Mysql 实现一个简易版搜索引擎.docx(63页珍藏版)》请在taowenge.com淘文阁网|工程机械CAD图纸|机械工程制图|CAD装配图下载|SolidWorks_CaTia_CAD_UG_PROE_设计图分享下载上搜索。
1、基于Mysql实现一个简易版搜索引擎何甜甜在吗链接:mysql>showvariableslike%ft_boolean_syntax%;+-+-+|Variable_name|Value|+-+-+|ft_boolean_syntax|+-><()*:&|+-+-+3.查询扩展模式:应用场景:查询的关键字太短,用户需要impliedknowledge(隐含知识)时进行。比如,对于单词database的查询,用户可能希望查询的不仅仅是包含database的文档,还指那些包含mysql、oracle、db2的单词。该查询会执行两次检索,第一次使用给定的短语进行检索,第二
2、次结合第一次相关性比较高的进行检索建立数据库:mysql>createtablearticles(->idintauto_incrementprimarykey,->titlevarchar(200),->bodytext,->fulltext(title,body)withparserngram->)->插入数据,插入数据库时可能会遇到的问题:ERROR1366(HY000):Incorrectstringvalue:xCAxFDxBExDDforcolumntitleatrow1编码方式有问题,默认好像为拉丁文解决方式一:altertableart
3、iclesconverttocharsetutf8;查看数据库中的数据:mysql>select*fromarticles;+-+-+-+|id|title|body|+-+-+-+|1|数据库管理|专业课|2|数据库|专业课|3|计算机操作系统|专业课|4|MySQL|专业课|5|MySQL数据库|专业课|+-+-+-+使用1、2、3三种模式查询数据库语法:select*fromtablewherematch(fulltext_field)against(find_keyinnaturallanguagemode|inbooleanmode|withqueryexpansion|inn
4、aturallanguagemodewithqueryexpansion)match:指定需要被查询的列against:指定使用何种方法进行查询模式一:自然语言模式mysql>select*fromarticleswherematch(title,body)against(MySQL数据库innaturallanguagemode);+-+-+-+|id|title|body|+-+-+-+|5|MySQL数据库|专业课|4|MySQL|专业课|1|数据库管理|专业课|2|数据库|专业课|+-+-+-+只要存在find_key中的字,记录就会被查询到默认采用naturallanguage
5、模式,因此上述sql语句等同于:select*fromarticleswherematch(title,body)against(MySQL数据库);模式二:布尔模式示例-1:查询既有数据,又有管理的记录mysql>select*fromarticleswherematch(title,body)against(+数据+管理inbooleanmode);+-+-+-+|id|title|body|+-+-+-+|1|数据库管理|专业课|+-+-+-+1rowinset(0.00sec)示例-2:查询有数据,没有管理的记录mysql>select*fromarticleswherem
6、atch(title,body)against(+数据-管理inbooleanmode);+-+-+-+|id|title|body|+-+-+-+|2|数据库|专业课|5|MySQL数据库|专业课|+-+-+-+2rowsinset(.00sec)示例-3:查询有MySQL,可以有数据库或没有数据库的记录mysql>select*fromarticleswherematch(title,body)against(>数据库+MySQLinbooleanmode);+-+-+-+|id|title|body|+-+-+-+|5|MySQL数据库|专业课|4|MySQL|专业课|+-+
7、-+-+2rowsinset(.00sec)模式三:查询扩展模式示例-4为了验证模式三,首先在数据库中插入以下数据:mysql>insertintoarticles(title,body)values->(MySQLTutorial,DBMSstandsforDataBase.),->(HowToUseMySQLWell,Afteryouwentthrougha.),->(OptimizingMySQL,Inthistutorialwewillshow.),->(1001MySQLTricks,1.Neverrunmysqldasroot.2.),->(My
8、SQLvs.YourSQL,Inthefollowingdatabasecomparision.),->(TuningDB2,ForIBMdatabase.),->(IBMHistory,DB2historyforIBM.);假设使用自然模式mysql>select*fromarticleswherematch(title,body)against(databaseinnaturallanguagemode);+-+-+-+|id|title|body|+-+-+-+|11|MySQLTutorial|DBMSstandsforDataBase.|12|HowToUseMyS
9、QLWell|Afteryouwentthrougha.|15|MySQLvs.YourSQL|Inthefollowingdatabasecomparision.|16|TuningDB2|ForIBMdatabase.|+-+-+-+只有四条查询结果,使用查询扩展模式mysql>select*fromarticleswherematch(title,body)against(databasewithqueryexpansion);+-+-+-+|id|title|body|+-+-+-+|12|HowToUseMySQLWell|Afteryouwentthrougha.|15|My
10、SQLvs.YourSQL|Inthefollowingdatabasecomparision.|11|MySQLTutorial|DBMSstandsforDataBase.|8|helloworld|Thisismyfirstjavaproject|13|OptimizingMySQL|Inthistutorialwewillshow.|16|TuningDB2|ForIBMdatabase.|17|IBMHistory|DB2historyforIBM.|14|1001MySQLTricks|1.Neverrunmysqldasroot.2.|9|article_1|Somelikeit
11、hot|4|MySQL|专业课|5|MySQL数据库|专业课|6|MySQL数据库|认真学习|10|article_2|Ilikehot|+-+-+-+查询出了13条语句。原先查询出的语句中即自然查询中包含MySQL、DB2这些字,所以进行扩展查询第二步时会将包含这些关键字的记录也查询出来。慎用查询扩展模式!因为可能会带来很多非相关性的查询查询返回结果是根据相关性进行降序排序的,相关性最高的结果放在第一位。相关性的计算依据四个条件1.findkey在文档中是否存在2.findkey在文档中出现的次数3.findkey在索引列的数量4.多少个文档包含该findkey以示例-3为例查询相关性,因为
12、后面又插了几条数据,结果和上述查询结果不一致mysql>selectid,title,body,match(title,body)against(MySQL数据库innaturallanguagemode)asrelevancefromarticles;+-+-+-+-+|id|title|body|relevance|+-+-+-+-+|1|数据库管理|专业课|0.1812381148338318|2|数据库|专业课|.1812381148338318|3|计算机操作系统|专业课|0|4|MySQL|专业课|.6349670886993408|5|MySQL数据库|专业课|1.1786
13、81492805481|6|MySQL数据库|认真学习|1.178681492805481|7|作文|好好写|0|8|helloworld|Thisismyfirstjavaproject|.0906190574169159|+-+-+-+-+id=8的记录相关性为0.09因为有个m吧底层实现原理只有了解了底层原理才可以更好的分析结果。全文索引的底层实现为倒排索引。为什么叫倒排索引倒排索引被称为反向索引更为合适当表上存在全文索引时,就会隐式的建立一个名为FTS_DOC_ID的列,并在其上创建一个唯一索引,用于标识分词出现的记录行。你也可以显式的创建一个名为FTS_DOC_ID的列,但需要和隐式
14、创建的列类型保持一致,否则创建的时候将会报错,并且不能通过FTS_DOC_ID来查找列:mysql>select*fromarticleswhereFTS_DOC_ID=1;ERROR1054(42S22):UnknowncolumnFTS_DOC_IDinwhereclause执行报错所以建立的articles表中列为FTS_DOC_ID、id、title、body常规的索引是文档到关键词的映射:文档>关键词倒排索引是关键词到文档的映射:关键词>文档全文索引通过关键字找到关键字所在文档,可以提高查询效率倒排索引结构NumberTextDocuments1code(1:6),
15、(4:8)2days(3:2),(6:2)3hot(1:3),(4:4)是word+ilist的存储结构Text对应于word,是一个分词。Document存储的是键值对,键为FTS_DOC_ID,值为在文档中的位置,对应于ilist。其中word保存在AuxiliaryTable中,总共有六张,每张表根据word的Latin编码进行分区,下面有介绍FTSIndexCache(全文检索索引缓存)在事务提交的时候将分词写入到FTSIndexCache中批量更新到AuxiliaryTable,为了提高性能不会插入一条数据立刻更新到AuxiliaryTable。进行批量更新的几种情况:全文检索索引缓
16、存已满,默认大小为32M,可以通过修改innodb_ft_cache_size来改变FTSIndexCache的大小关闭数据库的时候,将FTSIndexCache中的数据库会同步到磁盘上的AuxiliaryTable中当对全文检索进行查询时,首先会将在FTSIndexCache中对应的字段合并到AuxiliaryTable中,然后在进行查询当数据库突然宕机时,可能会导致一些FTSIndexCache中的数据未同步到AuxiliaryTable上。数据库重启时,当用户对表进行全文检索时,InnoDB存储引擎会自动读取未完成的文档,然后进行分词操作,在将分词的结果放入到FTSIndexCache中
17、。innodb_ft_cache_size的大小会影响恢复的时间FTSIndexCache为红黑树结构,会根据(word,ilist)进行排序插入AuxiliaryTable(辅助表)AuxiliaryTable存储在磁盘中,进入保存mysql数据的目录下tiantheL-SHC-15008567MINGW64/c/programdata/mysql/MySQLServer5.7/data/study$ls-lhtotal1.6M-rw-r-r-1tianthe10490898.5KApr1716:37articles.frm-rw-r-r-1tianthe1049089112KApr1717
18、:41articles.ibd-rw-r-r-1tianthe104908965Apr1715:24db.opt-rw-r-r-1tianthe104908996KApr1716:37FTS_000000000000005e_0000000000000087_INDEX_1.ibd-rw-r-r-1tianthe104908996KApr1716:37FTS_000000000000005e_0000000000000087_INDEX_2.ibd-rw-r-r-1tianthe104908996KApr1716:37FTS_000000000000005e_0000000000000087_
19、INDEX_3.ibd-rw-r-r-1tianthe104908996KApr1716:37FTS_000000000000005e_0000000000000087_INDEX_4.ibd-rw-r-r-1tianthe104908996KApr1716:37FTS_000000000000005e_0000000000000087_INDEX_5.ibd-rw-r-r-1tianthe104908996KApr1716:37FTS_000000000000005e_0000000000000087_INDEX_6.ibd-rw-r-r-1tianthe104908996KApr1716:
20、37FTS_000000000000005e_BEING_DELETED.ibd-rw-r-r-1tianthe104908996KApr1716:37FTS_000000000000005e_BEING_DELETED_CACHE.ibd-rw-r-r-1tianthe104908996KApr1716:37FTS_000000000000005e_CONFIG.ibd-rw-r-r-1tianthe104908996KApr1716:37FTS_000000000000005e_DELETED.ibd-rw-r-r-1tianthe104908996KApr1716:37FTS_00000
21、0000000005e_DELETED_CACHE.ibd看到有FTS_000000000000005e_0000000000000087_INDEX_06.ibd,其对应的就是六张AuxiliaryTable其余文件介绍:FTS_000000000000005e_DELETED.ibdFTS_000000000000005e_DELETED_CACHE.ibd记录的是从AuxiliaryTable中删除的FTS_DOC_ID,后者是前者的内存缓存FTS_000000000000005e_BEING_DELETED.ibdFTS_000000000000005e_BEING_DELETED_C
22、ACHE.ibd记录的是已经被删除索引记录并真正从FTSIndexCache删除的FTS_DOC_ID(即删除FTSIndexCache并做了OPTIMIZETABLE),后者是前者的内存缓存。这两个表主要用于辅助进行OPTIMIZETABLE时将DELETED/DELETED_CACHED表中的记录转储到其中FTS_000000000000005e_CONFIG.ibd包含全文索引的内部信息,最重要的存储是FTS_SYNCED_DOC_ID,表示已经解析并刷到磁盘的FTS_DOC_ID,在系统宕机时,可以根据这个值判断哪些该重新分词并加入到FTSIndexCache中DML操作插入操作插入操
23、作较为简单,当往表中插入记录时,提交事务时会对全文索引上的列进行分词存储到FTSIndexCache,最后在批量更新到AuxiliaryTable中删除操作当提交删除数据的事务以后,不会删除AuxiliaryTable中的数据,而只会删除FTSIndexCache中的数据。对于AuxiliaryTable中被删除的记录,InnoDB存储引擎会记录其FTSDocumentId,并将其保存在DELETEDAuxiliaryTable中。可以通过OPTIMIZETABLE手动删除索引中的记录。更新操作查找操作分为两步。第一步:根据检索词搜集符合条件的FTS_DOC_ID,在搜集满足条件的FTS_DO
24、C_ID首先读取delete表中记录的FTS_DOC_ID,这些FTS_DOC_ID随后被用做过滤第二步:根据FTS_DOC_ID找到对应的记录,找到的记录是根据相关性大小降序返回的查看插入记录的分词mysql>insertintot1values(NULL,hello,welcometomysqlworld);QueryOK,1rowaffected(1.87sec)mysql>setglobalinnodb_ft_aux_table=test/t1;QueryOK,rowsaffected(.00sec)mysql>select*fromINNODB_FT_INDEX_C
25、ACHE;+-+-+-+-+-+-+|WORD|FIRST_DOC_ID|LAST_DOC_ID|DOC_COUNT|DOC_ID|POSITION|+-+-+-+-+-+-+|hello|2|2|1|2|0|mysql|2|2|1|2|18|welcome|2|2|1|2|7|world|2|2|1|2|24|+-+-+-+-+-+-+皮皮甜这么做却没有查到分词情况,已经使用admin权限去设置global变量了,然而mysql>select*frominformation_schema.INNODB_FT_INDEX_TABLE;Emptyset(0.00sec)参考:httpmysql.taobao.org/monthly/2015/10/01/