2016-05-04 50 views
0

我有多个CURL脚本从许多内部公司网站收集数据到共享数据库。每个脚本被称为“实例”。数据以记录的形式添加到数据库中。每条记录都有多个“字段”,它们是键 - >值对。由于每条记录的关键字都是动态的,并且可以是任何东西(即使在同一个实例中),它们也不会被硬编码到MySQL表中。MySQL与MATCH查询和反对挂起

所以有这些表:

  1. 记录 - 包含记录列表,用
  2. record_fields实例的每个相关 - 包含一个记录相关的字段列表
  3. record_fields_labels - 基本上是一个标签列表。这存储在数据库中以节省空间(即,而不是record_fields有成千上万的字段,其标签为“文章日期”),它们将具有编号8,这是record_labels上具有“文章日期“作为它的价值)。

record_fields和record_fields_labels与关于“内容”(在包含实际数据的record_fields列)和“标记”(在record_fields_labels列具有标签名称)一个FULLTEXT索引二者MyISAM表。

该数据库拥有数百万的记录 - 每个多次记录中的字段... 当实例运行的数量来检查记录是否已在数据库中存在,他们做下面的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特别有关。我更愿意避免为所有内容(除了全文索引)增加索引以节省空间。

有谁知道是什么原因导致了这个挂断问题?

感谢

+0

您是否在SQL上运行了'EXPLAIN'来查看引擎如何运行查询? – syck

+0

而且:通常,智能构建的索引是找到或证明其存在的最有效的方法。那就是它的用途。 – syck

回答

0

看起来像您使用全文索引,你不必,尤其是对您的标签。如果这些都很简单并且定义良好,那么正常的索引就可以。如果您需要区分“文章日期”和“博客日期”,例如对于内容类型使用一个字段,对数据类型使用一个字段。

当您使用MATCH AGAINST ... IN BOOLEAN MODE搜索短语时,您实际上是按相同的顺序搜索相同的单词,而不是完整的字符串。看到DOCS

在你的领域的内容搜索“http://xxxx.yyy/www.zzz.mmm”实际上将匹配“这里的一些内容的HTTP,XXXX。YYY WWW!ZZZ嗯?是的,请,更多的内容”,而且是假设你的全文最小单词长度为3或减。对于性能和逻辑,这不是正确的索引。

我会认真考虑改变你的数据结构,以便你不把全文索引放在网址和标签上。这可能会比避免使用普通索引节省更多的空间。