我有多个CURL脚本,可以将许多内部公司站点的数据收集到共享数据库中。每个脚本都被称为"实例"。数据以记录的形式添加到数据库中。每条记录都有多个"字段",它们是键 - >值对。由于每个记录的键都是动态的,并且可以是任何记录(即使在同一个实例上),因此它们不会硬编码到MySQL表中。
所以有这些表:
record_fields和record_fields_labels都是MyISAM表,其上有一个FULLTEXT索引"内容" (record_fields中包含实际数据的列)和"标签" (record_fields_labels中具有标签名称的列)。
数据库有数百万条记录 - 每个记录数乘以... 当实例运行时,为了检查数据库中是否已存在记录,它们执行以下SQL查询:
SELECT r.id FROM records r INNER JOIN record_fields rf ON rf.record_id=r.id INNER JOIN record_fields_labels as rfl ON rf.label=rfl.id WHERE r.instance IN (120) AND MATCH (rf.content) AGAINST ('"http://xxxx.xxxx/xxx.xxx.xxx"' IN BOOLEAN MODE) AND MATCH (rfl.label) AGAINST ('"Article URL"' IN BOOLEAN MODE) GROUP BY r.id
在此示例中,http://xxxx.xxxx/xxx.xxx.xxx是脚本检查系统中是否已存在的文章的URL。
TL; DR
问题在于:当数据库很大(即数百万条记录/记录字段)时 - 上述查询就会挂断。查询将运行,甚至数小时,没有明显的原因。此相同的查询用于搜索收集的数据中的项目,这些项目似乎有效(或直到最近才工作)。
我想要的只是让它显示这样的记录是否存在。 它似乎不是一个索引问题,但与MATCH AGAINST有关。我宁愿避免使用所有内容的附加索引(除了FULL TEXT索引)来节省空间。
有人知道造成这种挂断问题的原因吗?
由于
答案 0 :(得分:0)
看起来您正在使用FULL TEXT索引,而不是必须使用,特别是对于您的标签。如果这些很简单且定义得很好,那么正常指数就可以了。例如,如果您需要区分“文章日期”和“博客日期”,请使用一个字段作为内容类型,一个字段作为数据类型。
当您使用MATCH AGAINST ...在BOOLEAN模式中搜索短语时,您实际上是以相同的顺序搜索相同的单词,而不是完整的字符串..请参阅DOCS
在您的字段内容中搜索“http://xxxx.yyy/www.zzz.mmm”实际上会匹配“http:xxxx.yyy www!zzz mmm?yes please,more content”中的某些内容,并假设您的全文最小字长为3或更少。对于性能和逻辑,这不是正确的索引。
我会认真考虑更改您的数据结构,这样您就不会在网址和标签上放置FULL TEXT索引。与避免使用普通索引相比,这可能会为您节省更多空间。