我测试了两个大的(每个约5密耳的记录)之间的更新,每次更新需要10秒左右。所以,我第一次做了解释测试选择:
SELECT
T1.Z, T2.Z
FROM
TableB T1
INNER JOIN TableL T2
on T1.Name=T2.Name
and T1.C=T2.C
and T1.S=T2.S
and T1.Number>=T2.MinNumber
and T1.Number<=T2.MaxNumber
Explain将以下内容作为可能的键返回:
并选择C作为关键。
有人告诉我,我最好的选择是制作一个复合键,按照选择的顺序,我做了
Alter Table TableB Add Index Compound (Name,C,S,Number)
又做了一个解释,希望它会选择我的化合物,但现在即使它显示复合指数作为可能的关键,它仍然选择指数C.
我读到我可以强制使用我想要的索引:
SELECT
T1.Z, T2.Z
FROM TableB T1 Force Index(Compound)
INNER JOIN TableL T2
on T1.Name=T2.Name
and T1.C=T2.C
and T1.S=T2.S
and T1.Number>=T2.MinNumber
and T1.Number<=T2.MaxNumber
但我不确定覆盖MySql的选择是否有任何意义,并且如果它没有帮助更新将花费将近两年的时间,那么测试似乎并不是一件好事。
我有什么步骤吗?我是否需要删除其他键以便选择我的复合键,如果是这样,我怎么知道它是否会产生影响(假设Mysql看到它并拒绝它)?
解释T1上的输出: (注意:我还没有添加复合索引,因为表格很大,可能是浪费时间,直到我想出来。我之前添加了它在一个高度截断的表格版本,但这将无助于解释) 表1
解释表2
基数 (仅显示与此相关的索引,因为还有其他几个):
小学:5139680
姓名:1284920
编号:57749
C:7002
S:21
答案 0 :(得分:3)
因此,基于一些出色的评论/输入,我想出了一个解决方案。来自Paul Spiegel的一个flashbulb输入是不建议尝试使用几个VarChar字段连接两个5 + mil表。
所以我做的是创建一个带ID和UnqiueRecord字段的UniqueTable。
然后我将UniqueRecord设为唯一索引。
我从TableA和TableB插入到该表中:
Insert IGNORE into `Unique` (UniqueRecord)
Select Concat(Name,C,S) from Table1 Group by Name,C,S;
Insert IGNORE into `Unique` (UniqueRecord)
Select Concat(Name,C,S) from Table2 Group by Name,C,S
这给了我两张表内和表之间的独特记录。
然后我在表1和表2中添加了一个UniqeRecord_ID字段。
然后我在每个表和UniqueRecord之间进行了连接,以便为每个表写入UniqueRecord ID:
Update Table1 as T1
Inner Join Unique as T2
On Concat(T1.Name,T1.S,T1.C) = T2.UniqueRecord
Set T1.UniqueRecord_ID=T2.ID
最后,我在UniqueRecord_ID上为每个表添加了一个键。
我的解释显示它只使用了来自T2的那个键,但是对于选择之前的每个记录需要10秒(我在1,10,100上测试并且在那里停止,因为我没有必要的578天来测试整个表:|)整个选择,返回接近500万条记录需要72秒。
答案 1 :(得分:0)
请注意,必须完全扫描第一个表格(无论哪个表格)。所以,我们能做的最好的就是在第二个表上有一个好的索引。
T1的最佳指数(如前所述)为(Name,C,S,Number)
。对于T2,它是(Name,C,S,MinNumber,MaxNumber)
,这是更大的。
优化器似乎想从T1开始;也许它稍微小一些。通过将INNER JOIN
更改为STRAIGHT_JOIN
并交换订单,强制它从T2开始:
SELECT
T1.Z, T2.Z
FROM TableL T2 -- note
STRAIGHT_JOIN TableB T1 -- note
on T1.Name=T2.Name
and T1.C=T2.C
and T1.S=T2.S
and T1.Number>=T2.MinNumber
and T1.Number<=T2.MaxNumber
然后,让我们再做一次优化:如果Z
不是太大&#39;,请将其包含在索引末尾,以便它变为a&#34;覆盖指数&#34;:
INDEX(Name,C,S,Number,Z)
(Name, C, S
可以按任何顺序排列,但Number, Z
必须按顺序排列,最后才是。)如果您目前有INDEX(Name)
,DROP
就是多余的。
然后EXPLAIN
会说你正在对T2进行全表扫描,加上一个&#34;使用索引&#34;在T1上。
请提供SHOW CREATE TABLE
;可能会有更多的优化。