用于优化的MySQL哈希索引

Hit*_*ony 7 mysql indexing hash b-tree

也许这可能是菜鸟,但我正在搞几张桌子.

我有表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
Run Code Online (Sandbox Code Playgroud)

所以我在ID,Lookup上强制索引.每个表都有这些列的索引,但由于子查询我强制它.

它正在运行,它真的应该采取,我想在5分钟之内......

我的问题是关于索引,而不是查询.

我知道你不能在有序索引中使用哈希索引.

我目前在ID,Lookup上都有索引,并且作为一个索引,它是一个B-Tree索引.基于我的WHEREClause,哈希索引是否适合作为优化技术?

我可以有一个哈希索引,其余的索引是B树索引吗?

这不是主要关键字段.

我会发布我的解释,但我更改了这些表上的名称.基本上它只是为ID使用索引...而不是使用ID,Lookup,我想强制它使用它们,或者至少把它变成另一种索引,看看是否有帮助?

现在我知道MySQL足够聪明,可以确定哪个索引最合适,那么它正在做什么?Lookup字段映射ID的第一部分和第二部分......

对此有任何帮助或见解表示赞赏.


 UPDATE

一个EXPLAINUPDATE我拿出子查询后.

+----+-------------+-------+------+-----------------------------+--------------+---------+-------------------+-------+-------------+
| 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树.

egg*_*yal 13

首先,处理您提出的具体问题:

  1. 我目前在ID,Lookup上都有索引,并且作为一个索引,它是一个B-Tree索引.基于我的WHEREClause,哈希索引是否适合作为优化技术?

    CREATE INDEX语法下所述:

    +----------------+--------------------------------+
    | Storage Engine |    Permissible Index Types     |
    +----------------+--------------------------------+
    | MyISAM         | BTREE                          |
    | InnoDB         | BTREE                          |
    | MEMORY/HEAP    | HASH, BTREE                    |
    | NDB            | BTREE, HASH (see note in text) |
    +----------------+--------------------------------+
    

    因此,在考虑HASH索引之前,应该意识到它MEMORYNDB存储引擎中可用:因此甚至可能不是您的选择.

    此外,请注意,单独IDLookup单独组合的索引可能不是最佳的,因为您的WHERE谓词也会过滤,tablea.Elg_IDpart1并且tableb.IDpart1您也可能从这些列的索引中受益.

  2. 我可以有一个哈希索引,其余的索引是B树索引吗?

    如果存储引擎支持所需的索引类型,您可以根据需要混合它们.

  3. 而不是使用ID,Lookup,我想强迫它使用它们,或者至少把它变成另一种索引,看看是否有帮助?

    您可以使用索引提示强制MySQL使用不同的索引,而不是优化器本来会选择的索引.

  4. 现在我知道MySQL足够聪明,可以确定哪个索引最合适,那么它正在做什么?

    通常很聪明,但并非总是如此.然而,在这种情况下,它可能已经确定索引的基数是这样的,以便最好使用它所选择的那些.


现在,根据您使用的MySQL版本,从子查询派生的表可能没有任何可用于进一步处理的索引:因此,连接b可能需要对该派生表进行全面扫描(此处的信息不足)你的问题确切地确定了这可能有多大的问题,但 schema1.tableb有150万条记录表明它可能是一个重要因素).

有关更多信息,请参阅子查询优化.

因此,如果可能的话,应该尽量避免使用派生表.在这种情况下,不出现任何目的,以派生表作为一个可以简单地连接schema1.tableaschema1.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
Run Code Online (Sandbox Code Playgroud)

唯一丢失的是DISTINCT记录过滤器,但重复记录将简单地(尝试)再次用相同的值覆盖更新的值 - 这将没有任何效果,但可能已经证明非常昂贵(特别是有这么多记录)那张桌子).

使用的ORDER BY派生表是毫无意义的,因为它可能不能依赖,来实现特定顺序的UPDATE,而在这个修订版也将确保覆盖以前的任何更新发生在特定的顺序:但是,这是必要的?也许它可以删除并保存在任何排序操作上.

应该检查WHERE子句中的谓词:它们是否都是必要的(例如,由于谓词将消除任何此类记录,因此NOT NULL检查a.ID并且b.Lookup是多余NULLJOIN)?

总而言之,这让我们:

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
Run Code Online (Sandbox Code Playgroud)

只有当性能仍然不令人满意时,才应该进一步研究索引.是否将相关列(即JOINWHERE谓词中使用的列)编入索引?是否选择了MySQL使用的索引(请记住,每个表只能使用一个索引进行查找:用于测试JOIN谓词和过滤谓词:可能需要一个合适的复合索引)?通过使用EXPLAIN进一步调查此类问题来检查查询执行计划.