选择列LIKE字典单词的行

时间:2012-09-15 14:43:59

标签: mysql sql

我有两张桌子:

Dictionary - 包含大约36,000个单词

CREATE TABLE IF NOT EXISTS `dictionary` (
  `word` varchar(255) NOT NULL,
  PRIMARY KEY (`word`)
) ENGINE=InnoDB DEFAULT CHARSET=latin1;

数据 - 包含大约100,000行

CREATE TABLE IF NOT EXISTS `datas` (
  `ID` int(11) NOT NULL AUTO_INCREMENT,
  `hash` varchar(32) NOT NULL,
  `data` varchar(255) NOT NULL,
  `length` int(11) NOT NULL,
  `time` int(11) NOT NULL,
  PRIMARY KEY (`ID`),
  UNIQUE KEY `hash` (`hash`),
  KEY `data` (`data`),
  KEY `length` (`length`),
  KEY `time` (`time`)
) ENGINE=InnoDB  DEFAULT CHARSET=latin1 AUTO_INCREMENT=105316 ;

我想以某种方式选择datasdata列包含1个或多个单词的所有行。

我理解这是一个很大的问题,它需要在每种可能的组合中将所有这些行匹配在一起,因此需要最佳的优化。

我已尝试过以下查询,但它只挂了很久:

SELECT      `datas`.*, `dictionary`.`word`
FROM        `datas`, `dictionary`
WHERE       `datas`.`data` LIKE CONCAT('%', `dictionary`.`word`, '%')
AND         LENGTH(`dictionary`.`word`) > 3
ORDER BY    `length` ASC
LIMIT       15

我还尝试了类似于上面的左连接,以及指定like语句的on子句。

3 个答案:

答案 0 :(得分:1)

这实际上不是一个简单的问题,您尝试执行的操作称为全文搜索,关系数据库不是执行此类任务的最佳工具。如果这是某种核心功能,请考虑使用专用于此类操作的解决方案,例如Sphinx Search Server

如果这不是“关键任务”系统,您可以尝试其他方法。我可以看到datas.data列不是很长,因此您可以创建专用于您的任务的结构,并在操作使用期间继续维护它。例如,创建表:

dictionary_datas (
    datas_id FK (datas.id),
    word FK (dictionary.word)
)

现在,无论何时插入,删除或只是修改数据或字典表,您都可以更新dictionary_datas,其中包含哪些datas_id包含哪些单词(基本上多对多关系)。当然,这会降低您的性能,因此如果您的系统上的事务负载很高,则必须定期执行此操作。例如,放置一个每晚03:00运行的Cron Job并实现该表。为了简化任务,您可以将标志TO_CHECK添加到DATAS表中,并仅为那些具有1的记录实现数据(在您实现dictionary_datas之后将值切换为0)。请记住在更新DICTIONARY表后刷新整个DATAS表的方法。在数据处理方面,36 000和10 000并不是一个大数字。

拥有此表后,您可以像查询一样:

SELECT datas_id, count(*) AS words_num FROM dictionary_datas GROUP BY datas_id HAVING count(*) > 3;

为了加快查询速度(并减慢它的更新速度),您可以在其datas_id,word(完全按顺序)列上创建复合索引。如果您决定定期刷新数据,则应在刷新之前删除索引,而不是刷新数据,最后在刷新后最终创建索引 - 这种方式会更快。

答案 1 :(得分:0)

我不确定我是否理解你的问题,但我认为这可能是一个解决方案。此外,我认为人们不喜欢正则表达式,但这对我来说可以选择其值超过1个单词的列。

SELECT * FROM datas WHERE data REGEXP“([a-z])+”

答案 2 :(得分:0)

你试过这个吗?

 select *
 from dictionary, datas
 where position(word,data) > 0 
 ;

效率非常低,但对你来说可能还不错。 Here is a fiddle

为了获得更好的效果,您可以尝试在文本列DATA上放置text search index,然后使用CONTAINS函数代替POSITION