【问题标题】:MySQL with multiple LIKE options. What's the alternative option?具有多个 LIKE 选项的 MySQL。什么是替代选择?
【发布时间】:2013-02-05 17:05:29
【问题描述】:

我正在编写 PDO 准备程序,但我想知道是否有另一种编写它的好方法,以便它运行得更快。 代码如下:

function comp_post_code($cat, $comp_post_code){
            global $DBH;
            $STH = $DBH->prepare("SELECT * from uk_data where 
                                    cat10 like :comp_post_code  AND (
                                    cat1 like :cat OR
                                    cat2 like :cat OR
                                    cat3 like :cat OR
                                    cat4 like :cat OR
                                    cat5 like :cat OR
                                    cat6 like :cat OR
                                    cat7 like :cat 

                                    )") ;
            $STH->bindValue(':cat', "%$cat%", PDO::PARAM_STR);
            $STH->bindValue(':comp_post_code', "$comp_post_code%", PDO::PARAM_STR);
            $STH->execute();
            $STH->setFetchMode(PDO::FETCH_ASSOC);
            return $STH;
            $DBH = Null;
            }

我想要表格中的完整数据,所以我使用 Select。 * ....谢谢

已编辑:- cat10 是邮政编码,cat 1 到 cat7 是类别。我需要搜索给定邮政编码中的类别。

表格格式如下:

CREATE TABLE IF NOT EXISTS `uk_data` (
  `slno` int(10) NOT NULL AUTO_INCREMENT,
  `comp_name` varchar(150) DEFAULT NULL,
  `comp_no` varchar(50) DEFAULT NULL,
  `comp_street` varchar(100) DEFAULT NULL,
  `comp_area` varchar(100) DEFAULT NULL,
  `comp_post_code` varchar(15) DEFAULT NULL,
  `comp_phone` varchar(100) DEFAULT NULL,
  `comp_phone1` varchar(100) DEFAULT NULL,
  `cat1` varchar(100) DEFAULT NULL,
  `cat2` varchar(100) DEFAULT NULL,
  `cat3` varchar(100) DEFAULT NULL,
  `cat4` varchar(100) DEFAULT NULL,
  `cat5` varchar(100) DEFAULT NULL,
  `cat6` varchar(100) DEFAULT NULL,
  `cat7` varchar(100) DEFAULT NULL,
  `cat8` decimal(9,6) DEFAULT NULL,
  `cat9` decimal(9,6) DEFAULT NULL,
  `cat10` varchar(15) DEFAULT NULL,
  PRIMARY KEY (`slno`),
  UNIQUE KEY `Phone` (`comp_phone`),
  KEY `cat10` (`cat10`)
) ENGINE=MyISAM  DEFAULT CHARSET=latin1 AUTO_INCREMENT=74504 ;

我正在使用的输出:

$uk_data_radious = comp_post_code($q,$pc_o);
            while (($row = $uk_data_radious->fetch()) !== false) {
            $comp_name[] = $row['comp_name'];
            $comp_phone[] = $row['comp_phone'];
            $comp_phone1[] = $row['comp_phone1'];
            $post_code[] = $row['cat10'];
            $post_code1[] = $row['comp_post_code'];
            $comp_no[] = $row['comp_no'];
            $comp_street[] = $row['comp_street'];
            $comp_area[] = $row['comp_area'];
            $cat1[] =  $row['cat1'];
            $cat2[] =  $row['cat2'];
            $cat3[] =  $row['cat3'];
            $cat4[] =  $row['cat4'];
            $cat5[] =  $row['cat5'];
            $cat6[] =  $row['cat6'];
            $cat7[] =  $row['cat7'];
            $distance_m[] = distance($Latitude[0],$Longitude[0],$row['cat8'],$row['cat9'],"M");
            }

【问题讨论】:

  • 你需要彻底重新设计你的表结构。如果您解释这些众多猫的用途,您将获得合理的结构和更好的查询
  • @YourCommonSense 我已经编辑了我的问题... :)
  • 您有示例典型查询吗?
  • @ring0 我已编辑问题请检查

标签: php mysql pdo sql-like


【解决方案1】:

Full Text search 在长字符串上的效果更好,可以在内部任何地方进行搜索。但它需要创建一个特殊的索引,并更改查询(并且与 InnoDB 表不兼容)。

这是一项相当不错的工作。但是如果 like 查询真的很慢,FTI(全文索引)是一个快速的选择。

--

保留 like 查询,您无能为力 - 当然除非改变您在列中组织数据的方式 - 即为了避免 like.

要以某种方式优化 like 查询,您可以将所有猫合并到一个列中(即添加一个新列 catx),并用一个特殊的字符分隔'不会出现在你的 cats 中,例如 :,并且只做一个“喜欢”(应该会加快一点)。例如

cat1: alpha
cat2: beta
cat3: gamma
...

给予

catx is :alpha:beta:gamma:

然后在 catx 上做类似的事情

catx like :cat
  • 要搜索特定的,请搜索“:mycat:”
  • 要搜索cat的一部分,以单词开头,搜索“:start”或
  • 要搜索结束词,请搜索“end:”

like 搜索算法在长字符串上比在较小的字符串上运行多次更有效。当搜索字符串超过 3 个字符时,MySQL 使用非常高效的Turbo Boyer-Moore algorithm

但我必须警告你:这个策略有几个限制因素

  • 不应出现在 cats 中的特殊分隔符
  • cat[1-7] 的任何更新都需要 catx 调整,所以如果 cats 可能会发生很大变化,也许这个不是一个好的解决方案
  • 此解决方案通常适用于格式很少更改的众所周知的数据(例如标识符)

从经验上看,我认为您不能期望通过这种策略获得超过 25% 的收益。

【讨论】:

  • 我不是投反对票的人,但我的猜测是 DV 是因为这个建议的结构会破坏第一个正常形式......重载单个列以包含多个甚至不相关的值可能会导致头痛在路上。
  • 这取决于数据结构 - 这是一个建议(因为没有奇迹可以显着改善 like 查询),需要在实施之前理解。最后一部分取决于 OP,因为我们不支持数据库和网站设计。
  • @ring0 我正在使用 MyISAM,正如您在我的问题中看到的那样......所有类别 cat 1 到 cat7 的 FULLTEXT 索引?
  • 您的类别听起来相当大(100 个字符),因此值得努力。 FTI 很快,但它需要一个设置(为你不想要的词调整字典等等......)。您需要对您的 like 查询/搜索进行基准测试,以激发这样的变化 - 再次,尤其是。对于 FTI,合并猫 - 添加新的 col catx - 也会有所帮助(需要仔细考虑如何管理数据 - 你是否更新 cats i> 很多等等...)。
  • @MichaelFredrickson 经过重新思考,我认为 DV 是应得的。我重建了答案并添加了一些警告。合并解决方案真的需要仔细考虑,并不是每个人都有平衡利弊的经验。
猜你喜欢
  • 2013-10-04
  • 2012-11-02
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2010-10-01
  • 2012-08-16
  • 2014-10-17
相关资源
最近更新 更多