2011-06-06 96 views
5

我有两个表:A - 301列(第一个名为a1 int(11)主键,第二个到第301个 - 双(15,11))& B - 33列(第一个 - b1 int(11)唯一键,第二个 - b2 varchar(100)主键,...,33rd - b33 int(11)MUL)。Mysql select on indexded column slowdown on large tables

A & B有~13,500,000条记录。

我的MySQL查询:对于POS的每一个值,在设定的POS(1,1000,2000,...,1350),1000的倍数:

选择A. *,B2,B5 ,b7,b8,b10,b13,b33来自a1 = b1上的A join B,其中b33> = pos和b33 < pos + 1000;

对于b33 < = 600,000的值,查询需要1-5秒。之后,查询开始花费20-30秒。当b33> = 8,000,000时,查询开始以60-70s开始。我不明白为什么发生放缓。 b33被编入索引,并且连接发生在一个表中被定义为主键且在另一个表中唯一的键上。有没有解决方法?这实际上阻碍了代码的速度,如果没有其他作用,我将不得不将表A & B分成几个较小的表。我真的希望我不必这样做!请帮忙!

编辑:这里是的O/P说明 -

** * ** * ** * ** * * 1行* ** * ** * ** * ** *
ID:1个
SELECT_TYPE:SIMPLE
表:乙
类型:范围
possible_keys:B1,B33
键:B33
key_len:4
REF:NULL
行:981
额外:使用其中
* ** * ** * ** * ** * 2。行* ** * ** * ** * ** *
ID:1个
SELECT_TYPE:SIMPLE
表:一个
类型:eq_ref
possible_keys: PRIMARY
key:PRIMARY
key_len:4
ref:DBName.B.b1
行:1
附加:
2行中集(0.00秒)

+0

那么你有一个特定的价值> 600,000的性能突然从5秒降到20秒? – 2011-06-06 06:42:54

+0

不,我更喜欢一个范围。发布650,000这是一场噩梦。 – ayesha129 2011-06-07 09:02:07

+0

我想这是解释慢速输出的输出。而快速的?有相同的输出吗? – Samuel 2011-06-07 12:27:24

回答

0

我没有MySQL的(或任何东西!)大师,但有些事情我会考虑。首先是b33均匀分布?可能会因为有效地检索更多行而变慢? 其次,您是否考虑过在单个查询中完成所有工作而不是13500?喜欢的东西:

select A.*, b2, b5, b7, b8, b10, b13, b33, (b33 - 1 DIV 1000) the_group 
from A join B on a1=b1 

第三,胡乱猜测,如果你的MySQL版本支持,使用inlinew视图做过滤第一:

select A.*, b2, b5, b7, b8, b10, b13, b33 
from A join (select b1,b2, b5, b7, b8, b10, b13, b33 
      from B b33 >= pos and b33 < pos+1000) B_NEW 
    on a1=b1 ; 

四(应该是第一),做一次解释计划,并尝试了解为什么查询比较慢,查询速度慢。

祝你好运!

+0

是的。 b33均匀分布。这里是解释的输出: – ayesha129 2011-06-07 09:06:18

+0

'*************************** 1. row *********** **************** ID:1个 SELECT_TYPE:SIMPLE 表:乙 类型:范围 possible_keys:I1,ID 键:ID key_len:4 REF:NULL 行数:981 额外:使用位置 *************************** 2。行*************************** id:1 select_type:SIMPLE 表:a 类型:eq_ref possible_keys:PRIMARY key :PRIMARY key_len:4 ref:ja_StepUp.b.resid rows:1 Extra: set 2行(0.00 sec) ' – ayesha129 2011-06-07 09:10:48

0

在黑暗中只是一个拍...

select A.*, b2, b5, b7, b8, b10, b13, b33 
    from A join B 
    on a1=b1 
    where b33 BETWEEN pos AND pos+999; 
0

你能告诉我们,你有B设定的指标? (感兴趣的是如何在B33指数的定义,以及它是否被定义在单个列或多个列):

SHOW INDEXES FROM B; 

你看到同样的速度下降时,你只从B选择?

select b2, b5, b7, b8, b10, b13, b33 from B where b33 >= pos and b33 < pos+1000; 

您能不能告诉我们

您正在使用的MyISAM或InnoDB的数据库引擎(允许感兴趣NULL)的部分从涉及领域B33的SHOW CREATE TABLE? (你可以在SHOW CREATE TABLE的结果中看到这个)。

0

解释计划和索引似乎很好。

我建议你比较配置文件,看看时间实在有云:

SET profiling=1; 

select A.*, b2, b5, b7, b8, b10, b13, b33 from A join B on a1=b1 where b33 >= 0 and b33 < 1000; 
SHOW PROFILE; 

select A.*, b2, b5, b7, b8, b10, b13, b33 from A join B on a1=b1 where b33 >= 1000000 and b33 < 1001000; 
SHOW PROFILE; 


SET profiling=0; 

,但我认为这可能是因为指数后600K的速度慢不适合到内存中再与更多的磁盘寻道做出

0

您需要更改此查询!

这里是你的旧的查询:

select A.*, b2, b5, b7, b8, b10, b13, b33 
from A join B on a1=b1 where b33 >= pos and b33 < pos+1000; 

这里是新的:

SELECT 
    AAA.*,b2,b5,b7,b8,b10,b13,b33 
FROM 
    A AAA INNER JOIN 
    (
     select 
      A.a1,b2,b5,b7,b8,b10,b13,b33 
     from 
      A INNER JOIN 
      (
       SELECT 
        b1,b2,b5,b7,b8,b10,b13,b33 
       FROM B 
       WHERE 
        b33 >= pos and 
        b33 < pos+1000 
      ) BB 
      ON A.a1=B.b1 
    ) BBB 
    USING (a1) 
; 

CAVEAT

这个重构查询的目的是使查询中的临时表计划尽可能小。实际上,子查询BBB在任何给定时间应该不会超过1000行。

试试吧!

0

ayesha129p,

尝试将b33约束移入连接子句。这听起来像是优化器只应用b33约束前连接集创建中的一个。

select A.*, b2, b5, b7, b8, b10, b13, b33 from A join B 
    on a1=b1 and b33 >= pos and b33 < pos+1000; 

这样优化器应该在尝试连接之前使用b33索引并将B行设置为1000。

1

由于您的数据库有数百万条记录,您是否在做任何事情来保持您的数据库的健康状况?

运行以下命令夜间可能与一般的响应速度帮助,如果您的数据频繁更改(许多刀片,也许?):

mysqlcheck --check --analyze --auto-repair --all-databases --silent

虽然我会在运行命令之前提示reading up a bit on mysqlcheck,只是让你知道它在做什么。

你也应该看看optimizing your InnoDB configuration,特别是innodb_buffer_pool_size(你可以给它的内存越多越好)。我在基于日期的字段(当然,我们立即索引)中遇到了类似大小的表中类似的缓慢,并且将缓冲池大小从默认的8兆字节增加到几千兆字节,这引起了非常显着的差异。

如果您要从联接中涉及的任何表中删除多行,那么也可以考虑运行OPTIMIZE TABLE