0

我有 2 张桌子:

字典- 包含大约 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 ;

我想以某种方式选择datas该列data包含 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 子句。

4

3 回答 3

1

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

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

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

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

一旦你有了这个表,你可以像这样查询它:

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

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

于 2012-09-15T15:27:13.243 回答
0

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

SELECT * FROM datas WHERE data REGEXP "([az] )+"

于 2012-09-15T15:36:22.123 回答
0

你试过这个吗?

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

这是非常低效的,但对你来说可能已经足够了。这是一个小提琴

为了获得更好的性能,您可以尝试在您的文本列上放置一个文本搜索索引DATA,然后使用该CONTAINS函数而不是POSITION.

于 2014-02-03T06:08:40.837 回答