mysql选择查询优化

时间:2012-11-22 13:19:18

标签: mysql performance select query-optimization

我有两张表testa& TESTB。

CREATE TABLE `testa` (
  `id` INT(10) NOT NULL AUTO_INCREMENT,
  `name` VARCHAR(50) DEFAULT NULL,
  PRIMARY KEY (`id`)
);

CREATE TABLE `testb` (
  `id` INT(10) NOT NULL AUTO_INCREMENT,
  `name` VARCHAR(50) DEFAULT NULL,
  `aid1` INT(10) DEFAULT NULL,
  `aid2` INT(10) DEFAULT NULL,
  `aid3` INT(10) DEFAULT NULL,
  PRIMARY KEY (`id`)
);

目前我在查询下面运行,以检索testa表中的id与tableb中的aid1,aid2,aid3的任何列匹配的所有行。查询正在检索精确结果,但执行时间最短为30秒,这太过分了。我也尝试使用UNION优化我的查询,但没有这样做。

SELECT a.id, a.name, b.name, b.id 
FROM testb b 
INNER JOIN testa a ON b.aid1 = a.id OR b.aid2 = a.id OR b.aid3 = a.id ;

如何优化查询,使其总执行时间在2-3秒内?

提前致谢...

EXPLAIN的结果:

id  select_type table   type    possible_keys   key key_len ref rows    Extra
1   SIMPLE  b   ALL idx_aid1,idx_aid2,idx_aid3  (NULL)  (NULL)  (NULL)  10940   
1   SIMPLE  a   ALL PRIMARY (NULL)  (NULL)  (NULL)  7512    Using where; Using join buffer

4 个答案:

答案 0 :(得分:4)

因为你允许aid1,aid2,aid3为NULL(显然,根据你的解释,它们大多数是NULL),你的连接条件实际上是不可索引的。

为什么呢? SQL表达式b.aid1 = a.id OR b.aid2 = a.id OR b.aid3 = a.id 如果任何aid1,aid2或aid3为NULL,则求值为NULL,这就是MySQL计划程序不使用索引显示的原因。

解决方案:不要对aid1,aid2,aid3使用NULL。相反,发明特殊的id(比如说0),它确保在testa中不存在。 然后,确保testb.aid [123]为非NULL(并将其分配给0之前为NULL)。

编辑:为此问题添加替代方法。

如果您可以通过添加一个表来更改架构,也可以解决此问题。这个新表将包含您当前存储在表testb中的辅助列表,而testb将只包含一个链接到新表的id。这应该与此answer中解释的类似。这样做的另一个好处是你可以允许任意数量的援助(不仅仅是你现在的3个)。

答案 1 :(得分:1)

除了其他人建议的索引之外,请确保ANALYZE表格,以便表格的统计信息是最新的。如果统计信息与表中的实际情况大不相同,那么查询规划器将做出错误的选择。

答案 2 :(得分:0)

您应该对以下列进行索引以避免全面扫描

  `aid1` INT(10) DEFAULT NULL,
  `aid2` INT(10) DEFAULT NULL,
  `aid3` INT(10) DEFAULT NULL,

如果你想改变表格

ALTER TABLE testb ADD INDEX (aid1);
ALTER TABLE testb ADD INDEX (aid2);
ALTER TABLE testb ADD INDEX (aid3);

答案 3 :(得分:0)

您是否尝试加入IN而不是OR

SELECT a.id, a.name, b.name, b.id FROM testb b INNER JOIN testa a ON a.id IN (b.aid1, b.aid2, b.aid3) ;