所以也许这就是菜鸟,但我正在搞几张桌子。
我有表A约45,000条记录
我有表B大约150万条记录
我有一个问题:
update
schema1.tablea a
inner join (
SELECT DISTINCT
ID, Lookup,
IDpart1, IDpart2
FROM
schema1.tableb
WHERE
IDpart1 is not NULL
AND
Lookup is not NULL
ORDER BY
ID,Lookup
) b Using(ID,Lookup)
set
a.Elg_IDpart1 = b.IDpart1,
a.Elg_IDpart2 = b.IDpart2
where
a.ID is NOT NULL
AND
a.Elg_IDpart1 is NULL
所以我在ID,Lookup上强制索引。每个表都有这些列的索引,但由于子查询我强制它。
它正在运行,它真的应该采取,我想在5分钟之内......
我的问题是关于索引,而不是查询。
我知道你不能在有序索引中使用哈希索引。
我目前在ID,Lookup上都有索引,并且作为一个索引,它是一个B-Tree索引。根据我的WHERE
子句,哈希索引是否适合作为优化技术?
我可以使用单个哈希索引,其余索引是B-tree索引吗?
这不是主要关键字段。
我会发布我的解释,但我更改了这些表上的名称。基本上它只是为ID使用索引...而不是使用ID,Lookup,我想强制它使用它们,或者至少把它变成另一种索引,看看是否有帮助?
现在我知道MySQL足够聪明,可以确定哪个索引最合适,那么它正在做什么? Lookup字段映射ID的第一部分和第二部分......
对此有任何帮助或见解表示赞赏。
我在取出子查询后EXPLAIN
上的UPDATE
。
+----+-------------+-------+------+-----------------------------+--------------+---------+-------------------+-------+-------------+ | id | select_type | table | type | possible_keys | key | key_len | ref | rows | Extra | +----+-------------+-------+------+-----------------------------+--------------+---------+-------------------+-------+-------------+ | 1 | SIMPLE | m | ALL | Lookup_Idx,ID_Idx,ID_Lookup | | | | 44023 | Using where | | 1 | SIMPLE | c | ref | ID_LookupIdx | ID_LookupIdx | 5 | schema1.tableb.ID | 4 | Using where | +----+-------------+-------+------+-----------------------------+--------------+---------+-------------------+-------+-------------+
tablea
相关索引:
ID_LookupIdx (ID, Lookup)
tableb
相关索引:
ID (ID)
Lookup_Idx (Lookup)
ID_Lookup_Idx (ID, Lookup)
所有索引都是正常的B树。
答案 0 :(得分:12)
首先,要处理你提出的具体问题:
我目前在ID,Lookup上都有索引,并且作为一个索引,它是一个B-Tree索引。根据我的
WHERE
子句,哈希索引是否适合作为优化技术?
正如CREATE INDEX
Syntax所述:
+----------------+--------------------------------+ | Storage Engine | Permissible Index Types | +----------------+--------------------------------+ | MyISAM | BTREE | | InnoDB | BTREE | | MEMORY/HEAP | HASH, BTREE | | NDB | BTREE, HASH (see note in text) | +----------------+--------------------------------+
因此,在考虑HASH
索引之前,应该意识到MEMORY
和NDB
存储引擎中只有 :所以可能不会甚至是你的选择。
此外,请注意,仅ID
和Lookup
组合的索引可能不是最佳的,因为WHERE
谓词也会过滤tablea.Elg_IDpart1
和{{1}你也可以从这些列的索引中受益。
我可以使用单个哈希索引,其余索引是B-tree索引吗?
如果存储引擎支持所需的索引类型,您可以根据需要混合它们。
而不是使用ID,Lookup,我想强迫它使用它们,或者至少把它变成另一种索引,看看是否有帮助?
您可以使用index hint强制MySQL使用与优化器原本选择的索引不同的索引。
现在我知道MySQL足够聪明,可以确定哪个索引最合适,那么它正在做什么?
通常足够聪明,但并非总是如此。然而,在这种情况下,它可能已经确定索引的基数是这样的,它最好使用它所选择的那些。
现在,根据您使用的MySQL版本,从子查询派生的表可能没有任何可用于进一步处理的索引:因此与tableb.IDpart1
的联接可能需要完整扫描派生表(你的问题中没有足够的信息来确定这可能有多少问题,但b
有150万条记录表明它可能是一个重要因素。)
有关详细信息,请参阅Subquery Optimization。
因此,如果可能的话,应该尽量避免使用派生表。在这种情况下,您的派生表似乎没有任何用途,因为您可以直接加入schema1.tableb
和schema1.tablea
:
schema1.tableb
唯一丢失的是UPDATE schema1.tablea a
JOIN schema1.tableb b USING (ID, Lookup)
SET a.Elg_IDpart1 = b.IDpart1,
a.Elg_IDpart2 = b.IDpart2
WHERE a.Elg_IDpart1 IS NULL
AND a.ID IS NOT NULL
AND b.IDpart1 IS NOT NULL
AND b.Lookup IS NOT NULL
ORDER BY ID, Lookup
记录的过滤器,但重复的记录将简单地(尝试)再次用相同的值覆盖更新的值 - 这将没有任何效果,但可能已证明非常成本高昂(特别是在该表中有如此多的记录)。
在派生表中使用DISTINCT
毫无意义,因为无法依赖它来实现ORDER BY
的任何特定顺序,而在此修订版本中它将确保覆盖的任何更新以前的那些按指定的顺序进行:但这是必要的吗?也许它可以删除并保存在任何排序操作上。
应该检查UPDATE
子句中的谓词:它们是否都是必要的(例如WHERE
上的NOT NULL
检查和a.ID
是多余的,因为任何谓词都是多余的这些b.Lookup
记录将被NULL
谓词删除?
总而言之,这让我们留下:
JOIN
只有当性能仍然不令人满意时,才能进一步了解索引。相关列(即UPDATE schema1.tablea a
JOIN schema1.tableb b USING (ID, Lookup)
SET a.Elg_IDpart1 = b.IDpart1,
a.Elg_IDpart2 = b.IDpart2
WHERE a.Elg_IDpart1 IS NULL
AND b.IDpart1 IS NOT NULL
和JOIN
谓词中使用的列)是否已编入索引?是否选择了MySQL使用的索引(请记住,每个表只能使用一个索引进行查找:用于测试WHERE
谓词和过滤谓词:也许你需要一个合适的综合指数)?使用JOIN
检查查询执行计划,以进一步调查此类问题。