2015-03-13 73 views
1

我使用MySQL 5.1.34,所有表都在Innodb Engine中。MySQL缓慢查询尽管EXPLAIN显示较少的行

我有如下3个表:

TableA (1M rows) 
-ID (Auto Increment PK) 
-TableB_ID 
-Date varchar(indexed) 
-Other Fields 

TableB (60M rows) 
-ID (Auto Increment PK) 
-TableC_ID 
-Other Fields 

TableC (10M rows) 
-ID (Auto Increment PK) 
-Other Fields 

我的目标是参加3个表,其匹配在表A的“日期”。 “日期”列被索引,一个简单的WHERE子句可以在秒内完成。例如。

SELECT * FROM TableA where date = '2015-03-13'; 
10000 rows in set (0.1 sec) 

但是,当我尝试使用下面的SQL连接TableB和TableC时,该过程变得非常慢。

SELECT A.*, C.Something FROM TableA A JOIN TableB B on A.TableB_ID = B.ID JOIN TableC C on B.TableC_ID = C.ID WHERE A.date = '2015-03-13'; 
10000 rows in set (20 sec) 

我试着用EXPLAIN命令排除缓慢,输出如下。

enter image description here

可能是什么原因?请帮忙!

+0

磁盘求.. ..? – 2015-03-13 10:57:14

+1

“A.TableB_ID”和“B.TableC_ID”是否被索引? – 2015-03-13 10:57:25

+0

@AbhikChakraborty EDITED。对不起,是A.TableB_ID和B.TableC_ID被索引。 – 2015-03-13 11:00:11

回答

0

正如我所说,这可能是一个磁盘寻找问题。就像你测量的那样,一旦记录存在内存中,查询就会很快,这对我来说确认了这个问题。

从磁盘中取出一个随机位置大约需要10ms,因为磁头必须移动。相关的记录可能聚集在磁盘上,服务器必须做大约。 20s/10ms = 20.000寻找。

的是几个明显的方法:

  • 使用一个SSD。没有求。
  • 向服务器添加足够的RAM以避免磁盘访问,或者为这些查询使用专用服务器(16GB看起来绰绰有余(虽然我不知道记录的大小),所以我猜还有其他常用的巨大的桌子)。
  • 缓存每个日期的结果 - 并将其存储在数据库中(memcached/redis/..)。如果记录对于旧日期是静态的,那么这可能非常有效,因为您不必担心缓存失效。

不管怎么说,做一些后台计算和计算内存需求可能是个好主意。

0

你没有提供SHOW CREATE TABLE就遗漏了很多重要的信息,但我会做一些猜测。

你真的抓取10K行吗?你打算怎么处理所有这些问题?获取那么多行需要时间。

如果您使用的是MyISAM,那么B将从INDEX(ID, TableC_ID)获益良多。 InnoDB不应该从中受益,除非表格非常“宽”。

SHOW VARIABLES LIKE '%buffer%';你有多少RAM?

是否正在使用查询缓存?如果是这样,那将解释为什么第二次如此之快。大多数生产系统发现最好关闭QC。