【发布时间】:2016-03-16 07:39:58
【问题描述】:
我在连接两个表时遇到了问题。一个140M行的大表,另一个是100行的小表,同时加入主键。
这两个表是:
DataTable
{
Date timestamp,
Hash varchar(20),
Type varchar(20),
Purchases int,
Store varchar(20),
Primary key (Date, Hash)
}
DataTable 是一个非常大的表,有 1.4 亿行
ProductTable
{
Hash varchar(20),
Name varchar(20),
Primary key (Hash)
}
ProductTable 是只有 100 行的小表
我运行了两个单独的查询
Select sum(DataTable.Purchases),DataTable.Store
from DataTable
Join ProductTable on ProductTable.Hash = DataTable.Hash
Where Type =2
and Date<='2015-12-31'
and Date>='2015-1-1'
group by DataTable.Store
这花了很长时间(实际上永远不会结束)。运行解释时,这表明它处理了几乎一半的表。如本说明所示:
select_type |table |type |possible_keys|key | key_len | ref |rows |Extra |
-----------------------------------------------------------------------------
Simple |DataTable |All |Date, Hash |Null | Null | Null |7*10^7|using where
Simlpe |ProductTable| eq_ref |PRIMARY PRIMARY | 386 | ProductTable.Hash | 1 | Using where |
只是为了好玩,我从 ProductTable 中提取了所有相关的哈希值,并将它们放在 Where In 子句中。像下面这样:
Select sum(DataTable.Purchases),DataTable.Store
From DataTable
Where DataTable.Hash in ("1ha84u","1ha850","1ha851",...,"1hl931")
Type =2
and DataTable.Date<='2015-12-31'
and DataTable.Date>='2015-12-1'
group by DataTable.Store
这带来了更好的性能 - 耗时不到 2 秒,扫描的行数也更少。
select_type |table |type |possible_keys|key | key_len | ref |rows |Extra |
----------------------------------------------------------------------------
Simple |DataTable |range |Date, Hash |Date, Hash | 62 | Null|11097|using where
我不明白为什么第一个查询没有使用主键,为什么第二个查询会带来更好的性能。
我已经确保结果没有被 MySql 在运行之间缓存。
【问题讨论】:
-
你能在第一次查询中运行一个解释,只是这次包括一个关于日期的强制索引提示,哈希索引? dev.mysql.com/doc/refman/5.7/en/index-hints.html
-
它们是具有不同结果的不同查询。第一个将显示与 3 个 where 子句匹配的所有行,将
ProductTable的信息添加到 deDatatable。第二个只显示与Hash列表匹配的Datatable的信息,另一个是 where 子句。 -
顺便说一句,第二个查询要快得多,因为它使用索引从数据表中选择数据。