慢的mysql查询。有小费吗?

时间:2009-12-15 23:27:53

标签: sql mysql optimization

我有以下查询...它可以运行,但运行速度非常慢。希望有人可以给我一些改进执行时间的技巧吗?

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;

7 个答案:

答案 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_idtb_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

这是故意的吗?)