【问题标题】:How find phrase (words) at beginning of text如何在文本开头找到短语(单词)
【发布时间】:2014-01-17 11:12:50
【问题描述】:

如何在文本开头找到短语(单词)

我需要非常快速的解决方案来找出文本是否以某些已知短语开头

我在 Mysql (innodb) 表中的短语如下:

CREATE TABLE IF NOT EXISTS `phrase` (
  `id` int(10) unsigned NOT NULL,
  `text` varchar(255) NOT NULL,
  PRIMARY KEY (`id`),
  UNIQUE KEY `text` (`text`)
) ENGINE=InnoDB;

INSERT INTO phrase VALUES (1, 'one');
INSERT INTO phrase VALUES (2, 'one two');
INSERT INTO phrase VALUES (3, 'two');
INSERT INTO phrase VALUES (4, 'three');

短语文本是一个或多个单词。 表包含大约 20.000 行

现在我从用户请求中获取文本,并且需要知道该文本是否像任何短语一样开头。 但我需要找出数据库中最长的短语

我应该将行预缓存到服务器内存,或者我可以在 mysql 表中搜索。

我试过了

 $_REQUEST['text'] = 'one two three';
 $_REQUEST['text'] = explode(' ', $_REQUEST['text']);
 $search = ''; $found = null;
 foreach ($_REQUEST['text'] as $next_word) {
  $search .= (($search == '') ? '' : ' ').$next_word;
  $query = "SELECT SQL_CACHE * FROM phrase WHERE phrase = '{$search}' LIMIT 1;";
  ...
  $row = mysql_fetch_assoc($result);
  if ( ... not found ... ) break;
   else $found = $row;
 }
 print_r($row); // print latest found phrase "one two"

我觉得这种方式很慢,因为我需要对每个单词进行全表扫描

您知道更快的解决方案吗?

【问题讨论】:

    标签: php mysql sql


    【解决方案1】:

    改为

    $query = "SELECT SQL_CACHE * FROM phrase WHERE phrase = '{$search}' LIMIT 1";
    

    你可以这样做:

    $query = "SELECT SQL_CACHE * FROM phrase WHERE phrase like '%{$search}%' LIMIT 1";
    

    或者另外你可以像这样减少你的代码:

    $count = count($_REQUEST['text']);
    $where = "";
    for($loop=0;$count<$loop;$loop++) {
    if($loop!=($count-1))
     $where .= "phrase like '%".$_REQUEST['text'][$loop]."%' OR";
    else 
     $where .= "phrase like '%".$_REQUEST['text'][$loop]."%'";
    }
    $query = "SELECT SQL_CACHE * FROM phrase WHERE $where LIMIT 1;";
    

    【讨论】:

    • like 比短语 = '{$search}' 的 CPU 和 IO 更密集
    • @user5332 我认为这是你能拍到的最好的照片。您也可以使用子字符串,但成本会更高。
    【解决方案2】:

    你可以像这样使用正则表达式:

    SELECT * FROM phrase WHERE `text` REGEXP '^(one (two (three)?)?)';
    

    这可以在没有foreach 循环的情况下工作,因为正则表达式是贪婪的并且会产生可能的最长匹配。它只使用索引,不做任何表扫描,所以速度也很快。

    不过,您必须小心用户输入(一如既往)。

    【讨论】:

      【解决方案3】:

      您可以使用索引,这样您就可以避免全表扫描,并且每次都能在第一次拍摄时访问准确的行。

      create index btree on test(phrase)
      

      【讨论】:

        猜你喜欢
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 2010-11-26
        • 2022-11-25
        • 2011-04-21
        • 1970-01-01
        • 1970-01-01
        • 2015-08-28
        相关资源
        最近更新 更多