我有以下查询...它可以运行,但运行速度非常慢。希望有人可以给我一些改进执行时间的技巧吗?
SELECT tb_clients.*, tb_clients_phone_fax.*
FROM tb_clients, tb_clients_phone_fax
WHERE tb_clients.client_id=tb_clients_phone_fax.client_id
AND MATCH (client_company,client_description,client_keywords) AGAINST ('test') > 0
AND CONCAT(client_address,' ',client_city,', ',client_state,' ',client_zip) LIKE '%brooklyn%'
LIMIT 10;
编辑:
以下是表格信息:
CREATE TABLE `tb_clients` (
`client_id` int(11) unsigned NOT NULL AUTO_INCREMENT,
`client_company` varchar(254) NOT NULL,
`client_address` varchar(254) NOT NULL,
`client_street` varchar(254) NOT NULL,
`client_city` varchar(254) NOT NULL,
`client_state` varchar(254) NOT NULL,
`client_zip` varchar(45) NOT NULL,
`client_email` varchar(254) NOT NULL,
`client_website` varchar(254) NOT NULL,
`client_description` text NOT NULL,
`client_keywords` text NOT NULL,
PRIMARY KEY (`client_id`) USING BTREE,
FULLTEXT KEY `client_company` (`client_company`,`client_description`,`client_keywords`)
) ENGINE=MyISAM AUTO_INCREMENT=68347 DEFAULT CHARSET=latin1;
和
CREATE TABLE `tb_clients_phone_fax` (
`client_phone_fax_id` int(11) unsigned NOT NULL AUTO_INCREMENT,
`client_id` int(11) unsigned NOT NULL,
`client_phone_1` varchar(45) NOT NULL,
`client_phone_2` varchar(45) NOT NULL,
`client_phone_3` varchar(45) NOT NULL,
`client_fax_1` varchar(45) NOT NULL,
`client_fax_2` varchar(45) NOT NULL,
`client_fax_3` varchar(45) NOT NULL,
PRIMARY KEY (`client_phone_fax_id`) USING BTREE
) ENGINE=MyISAM AUTO_INCREMENT=33944 DEFAULT CHARSET=latin1 ROW_FORMAT=DYNAMIC;
答案 0 :(得分:2)
tb_clients.client_id和tb_clients_phone_fax.client_id应编入索引。
但主要问题似乎是两个字符串比较,MATCH和LIKE与CONCAT。你确定周围没有其他战争吗?比如,在执行LIKE语句之前避免连接所有地址字段?
更新:似乎tb_clients_phone_fax.client_id没有编入索引,如果将其编入索引,它会提高性能。
答案 1 :(得分:1)
没有看到表格架构,很难肯定地说,但我认为这是因为你没有搜索任何指标。
尝试查看有关全文搜索的MySQL手册:http://dev.mysql.com/doc/refman/5.0/en/fulltext-search.html 为了获得更好的答案,您很可能需要发布您的架构和指标。
答案 2 :(得分:1)
首先,您应确保tb_clients
的索引为client_id
,tb_clients_phone_fax
的索引为client_id
。
然后尝试为客户公司,客户描述,客户关键字添加索引。
但是,我愿意打赌,对于您在连锁client_address,client_city,client_state,client_zip
上进行的比较,主要的减速速度即将到来,因此请尝试找一些其他方法来进行此比较,而不需要使用concat。你可以在表中添加一个字段来保存连接的那些项的数据,然后只在该字段上进行比较吗? (我知道丑陋)
答案 3 :(得分:1)
对你的情况一无所知,除了上面提到的索引之外,我的第一个想法是:这两个表中有多少行?其中一个只有几千而另一个是一千万?假设您的查询性能不是由于加入非常大的数据集,那么:
正如其他人所说,请检查您的列是否已编入索引。另外,为什么不是全文索引你连接的列,然后在你的查询中使用第二个MATCH()AGAINST()而不是CONCAT()和LIKE?
如何更新代码以检查邮政编码模式,然后相应地编写查询?或者说,如果它不是一个邮政编码模式,那么就不用费心去搜索那一列了。
在需要搜索整个(大)表的高容量情况下,对我来说效果很好的一件事是创建一个包含整个表的串联的列。我在该列上放了一个全文索引并使用MATCH()AGAINST()并且查询时间非常快 - 所以根据我的经验,全文索引可以完成工作。
现在,如果你有一个非常大的表,那么实时加入可能会变得不可接受。此时,您有几个选项,但所有这些选项都是在后台加入并存储该结果的变体,以便最终用户体验。
答案 4 :(得分:1)
调试慢速查询的第一步正在运行EXPLAIN SELECT ...
并查看MySQL实际在做什么,而不是猜测。但是,正如其他人所说的那样,tb_clients_phone_fax.client_id
上的索引看起来确实会有所帮助。
答案 5 :(得分:0)
我会为表格tb_clients创建一个视图,其中包含一个包含连接信息的“假”列。
另外,我会索引前面提到的id列。
然后你将使用相同的基本查询,替换表的视图并省略concat(因为它是由视图作为聚合列完成的)
离开工作我5分钟,所以我不能详细说明。如果您需要代码,示例sql等让我知道,我将在今晚或明天为您提供一些东西。
答案 6 :(得分:0)
一个非常小的提示:
CONCAT(client_address,' ',client_city,', ',client_state,' ',client_zip) LIKE '%brooklyn%'
整个CONCAT是否必要?您的州或邮政编码中是否有许多客户brooklyn
?
(另外,你意识到这会匹配像
这样的地址 1342 Brooklyn Street
Foobar,MI 98765
这是故意的吗?)