2015-02-08 124 views
1

我有非常大的客户数据库。在添加ORDER BY之前,此查询是可以的。我怎样才能优化我的查询速度?为什么这个INNER JOIN/ORDER BY mysql查询太慢?

$sql = "SELECT * FROM customers 
LEFT JOIN ids ON customer_ids.customer_id = customers.customer_id AND ids.type = '10' 
ORDER BY customers.name LIMIT 10";

ids.typecustomers.name是我的指标

解释查询

 
id select_type table  type possible_keys key  key_len  ref  rows Extra 
1 SIMPLE  customers ALL  NULL   NULL NULL  NULL 955  Using temporary; Using filesort 
1 SIMPLE  ids  ALL  type   NULL NULL  NULL 3551 Using where; Using join buffer (Block Nested Loop)
+0

如果您可以将其他字段添加好的索引,请这样做。这是有道理的,因为按顺序排列,它需要整个结果集才能重新排列。另外,你的主键是什么? – 2015-02-08 03:21:20

+3

您的查询语法错误。 'customer_ids'没有被定义。 – 2015-02-08 03:23:42

+0

他指的是customer_ids被用在他的连接标准中,但事实上并不是加入的表中的一个。你能在上面的查询中显示EXPLAIN的结果吗? – BK435 2015-02-08 03:51:28

回答

1

(我假设你想键入ids.customer_id = customer.customer_id而不是customer_ids.customer_id)

没有ORDER BY mysql抓住了10型(索引)的前10个ID,抬起头看着cu对他们来说,他们已经完成了。 (请注意,LEFT JOIN这里真的是一个INNER JOIN因为连接条件将仅保持有两个表中的匹配行)

与ORDER BY MySQL是可能获取所有类型= 10个客户,然后排序他们通过名字找到前10个。

您可以通过反规范化客户表(将该类型复制到客户记录)或创建映射表来保存元组来加快速度。无论哪种情况,请在(type, name)上添加索引。如果使用映射表,请使用它与客户和ID进行三方联接。

如果type = 10是相当常见的,那么您也可以强制查询按照名称来遍历customers表,并通过STRAIGHT JOIN检查每个类型。它不会像复合指数那样快,但它会比提起所有比赛更快。

如上所示,对查询运行EXPLAIN以查看mysql正在使用的查询计划。

+0

什么是“STRAIGHT”连接? – 2015-02-08 07:49:48

+0

直接连接是一个mysql连接类型,用于遍历左表并连接右表找到的行。与查询优化器选择读取表的顺序的其他连接不同,直接连接允许程序员指定。 – Andras 2015-02-08 07:56:43

+0

我添加了EXPLAIN查询记录 – lingo 2015-02-08 14:58:46

0

LEFT是问题所在。通过说LEFT JOIN,您暗示某些customersids中可能没有相应的行。而且,您愿意接受NULL的字段来代替这样的ids行。

如果不是这种情况,请移除LEFT。然后确保你有一个ids的索引开始type。此外,customers必须具有从customer_id开始的索引(可能是PRIMARY KEY)。有了这些,优化器可以从ids开始,在type上过滤,从而减少了工作量。

但是,它仍然必须收集大量的行之前做排序(ORDER BY);只有这样才能交付10个(LIMIT)。

当你在它的时候,将INDEX(customer_id)加到ids - 这就是杀死LEFT版本的性能。