所以也许这不是菜鸟,但我正在弄乱几张 table 。
我有表 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 sperately 和作为一个索引上都有索引,它是一个 B-Tree 索引。根据我的 WHERE
子句,哈希索引是否适合作为优化技术??
我可以有一个单一的哈希索引,其余的索引都是 B 树索引吗?
这不是主键字段。
我会发布我的解释,但我更改了这些表的名称。基本上它只为 ID 使用索引...而不是使用 ID,Lookup,我想强制它同时使用两者,或者至少将它变成另一种索引,看看是否有帮助?
现在我知道 MySQL 足够聪明,可以确定最合适的索引,那么它在做什么? Lookup 字段映射 ID 的第一部分和第二部分...
在此方面提供任何帮助或见解,我们将不胜感激。
更新
在我取出子查询后,UPDATE
上的 EXPLAIN
。
+----+-------------+-------+------+-----------------------------+--------------+---------+-------------------+-------+-------------+ | 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,查找)
tableb
相关索引:
身份证(ID)
Lookup_Idx(查找)
ID_Lookup_Idx(ID,查找)
所有的索引都是普通的 B 树。
最佳答案
首先针对您提出的具体问题进行处理:
-
I currently have indexes on both ID, Lookup sperately, and as one index, and it is a B-Tree index. Based on my
WHERE
Clause, does a hash index fit for as an optimization technique??根据
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
和tableb.IDpart1
- 您也可以从这些列的索引中受益。 -
Can I have a single hash index, and the rest of the indexes b B-tree index?
只要存储引擎支持所需的索引类型,您可以根据需要混合使用它们。
-
instead of using the ID, Lookup, I would like to force it to use both, or at least turn it into a different kind of index and see if that helps?
你可以使用 index hint强制 MySQL 使用与优化器原本选择的索引不同的索引。
-
Now I know MySQL is smart enough to determine which index is most appropriate, so is that what it's doing?
它通常足够聪明,但并非总是如此。然而,在这种情况下,它可能已经确定索引的基数使得最好使用它选择的索引。
现在,根据您使用的 MySQL 版本,从子查询派生的表可能没有任何可用于进一步处理的索引:因此与 b
的连接可能需要一个对该派生表进行全面扫描(您的问题中没有足够的信息来确定这可能到底有多大问题,但是 schema1.tableb
有 150 万条记录表明它可能是一个重要因素)。
参见 Subquery Optimization获取更多信息。
因此,应尽可能避免使用派生表。在这种情况下,您的派生表似乎没有任何用途,因为可以直接连接 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
和 WHERE
谓词中使用的列)是否已编入索引?索引是否被选择供 MySQL 使用(请记住,每个表只能使用 一个 索引进行查找:用于测试 JOIN
谓词和过滤谓词:也许你需要一个合适的综合指数)?使用 EXPLAIN
检查查询执行计划以进一步调查此类问题。
关于用于优化的 MySQL 哈希索引,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/21049449/