不同的排序规则或 character_set 值会影响查询优化器对索引的使用吗?

Can differing collation or character_set values affect query optimizer use of indexes?

使用 MariaDB 10.3.28。我要加入 4 tables.

  1. 查询优化器正确使用了 3 个 table 的索引并扫描了主要的 table、table #1。查询在 6 秒内运行。
  2. 我用新版本的 table #1 交换了一些添加的列,其中 none 用于查询,并且一些列重命名。现在我的查询只使用 4 号 table 上的索引,导致糟糕的性能。查询耗时63分钟!
  3. 我比较了 table 并注意到旧的 table 使用 latin1 character_set 和 latin1_swedish_ci 排序规则。
  4. 较新的 table 使用 utf8 character_set 和 utf8_general_ci 排序规则。

来自 table #1 的连接中的关键字段是否有任何机会,它是一个 varchar(20),没有得到优化以使用较新的 table #1 的索引作为character_set 和排序规则不同的结果?其他 3 个 table 使用与旧 table #1 相同的设置(latin1latin1_swedish_ci)。

这是 2 个 EXPLAINed 查询。 旧 table #1:

EXPLAIN SELECT DISTINCT
    h.dataareaid,
    h.warehouseid,
    h.itemno,
    h.qoh,
    p.eau,
    h.fifo_cost,
    (h.qoh * h.fifo_cost) AS value,
    ((p.cuft_inner / p.pcs_inner) * h.qoh) AS cuft,
    p.status,
    CASE WHEN (p.status = 'P'
        OR p.isprivatelabel = 1
        OR p.sales_category_id = 7
        OR ph.smoothie_enabled != 1
        OR pe.firstsold > CURDATE() - INTERVAL 1 YEAR
        OR p.added > CURDATE() - INTERVAL 9 MONTH) THEN
        0
    ELSE
        GREATEST(h.qty_avail - p.sold - p.allocated_qty - p.eau, 0)
    END AS excess_qty,
    CASE WHEN (p.status = 'P'
        OR p.isprivatelabel = 1
        OR p.sales_category_id = 7
        OR ph.smoothie_enabled != 1
        OR pe.firstsold > CURDATE() - INTERVAL 1 YEAR
        OR p.added > CURDATE() - INTERVAL 9 MONTH) THEN
        0
    ELSE
        GREATEST((h.qty_avail - p.sold - p.allocated_qty - p.eau) * h.fifo_cost, 0)
    END AS excess_value
FROM
    fiat.parts_warehouse_items h
    LEFT JOIN fiat.parts p ON p.itemno = h.itemno
    LEFT JOIN fiat.parts_ext pe ON pe.itemno = h.itemno
    LEFT JOIN internal.parts_history ph ON ph.itemno = h.itemno
        AND ph.date = CURRENT_DATE
WHERE
    h.warehouseid != 'AllBlank'
GROUP BY
    h.dataareaid,
    h.warehouseid,
    h.itemno;
+------+-------------+-------+--------+------------------------------------------------------------------------------------------------------------------------------------------------------+---------+---------+----------------------------+-------+----------------------------------------------+
| id   | select_type | table | type   | possible_keys                                                                                                                                        | key     | key_len | ref                        | rows  | Extra                                        |
+------+-------------+-------+--------+------------------------------------------------------------------------------------------------------------------------------------------------------+---------+---------+----------------------------+-------+----------------------------------------------+
|    1 | SIMPLE      | h     | ALL    | NULL                                                                                                                                                 | NULL    | NULL    | NULL                       | 59644 | Using where; Using temporary; Using filesort |
|    1 | SIMPLE      | p     | eq_ref | PRIMARY,itemno_category_class,itemstatus,itemstatuscolordescription,itemcolordescription,marketing,itemnodescription,itemnodescriptionupc,itemprices | PRIMARY | 32      | fiat.h.itemno              |     1 | Using where                                  |
|    1 | SIMPLE      | pe    | eq_ref | PRIMARY,itemno                                                                                                                                       | PRIMARY | 20      | fiat.h.itemno              |     1 | Using where                                  |
|    1 | SIMPLE      | ph    | eq_ref | PRIMARY,date,itemno,itemno_2,date_2,eau_dollars                                                                                                      | PRIMARY | 50      | const,fiat.h.itemno        |     1 | Using where                                  |
+------+-------------+-------+--------+------------------------------------------------------------------------------------------------------------------------------------------------------+---------+---------+----------------------------+-------+----------------------------------------------+

新 table #1:

EXPLAIN SELECT DISTINCT
    h.dataareaid,
    h.warehouse_id AS warehouseid,
    h.sku AS itemno,
    h.qty_onhand AS qoh,
    p.eau,
    p.fifo_cost,
    (h.qty_onhand * p.fifo_cost) AS value,
    ((p.cuft_inner / p.pcs_inner) * h.qty_onhand) AS cuft,
    p.status,
    CASE WHEN (p.status = 'P'
        OR p.isprivatelabel = 1
        OR p.sales_category_id = 7
        OR ph.smoothie_enabled != 1
        OR pe.firstsold > CURDATE() - INTERVAL 1 YEAR
        OR p.added > CURDATE() - INTERVAL 9 MONTH) THEN
        0
    ELSE
        GREATEST(h.qty_total_available - p.sold - p.allocated_qty - p.eau, 0)
    END AS excess_qty,
    CASE WHEN (p.status = 'P'
        OR p.isprivatelabel = 1
        OR p.sales_category_id = 7
        OR ph.smoothie_enabled != 1
        OR pe.firstsold > CURDATE() - INTERVAL 1 YEAR
        OR p.added > CURDATE() - INTERVAL 9 MONTH) THEN
        0
    ELSE
        GREATEST((h.qty_total_available - p.sold - p.allocated_qty - p.eau) * p.fifo_cost, 0)
    END AS excess_value
FROM
    lancia.warehouse_inventory AS h
    LEFT JOIN fiat.parts p ON p.itemno = h.sku
    LEFT JOIN fiat.parts_ext pe ON pe.itemno = h.sku
    LEFT JOIN internal.parts_history ph ON ph.itemno = h.sku AND ph.date = CURRENT_DATE
WHERE
    h.warehouse_id != 'AllBlank'
GROUP BY
    h.dataareaid, h.warehouse_id, h.sku;
    +------+-------------+-------+------+---------------------+---------+---------+-------+--------+--------------------------------------------------------+
| id   | select_type | table | type | possible_keys       | key     | key_len | ref   | rows   | Extra                                                  |
+------+-------------+-------+------+---------------------+---------+---------+-------+--------+--------------------------------------------------------+
|    1 | SIMPLE      | h     | ALL  | NULL                | NULL    | NULL    | NULL  |  63068 | Using where; Using temporary; Using filesort           |
|    1 | SIMPLE      | p     | ALL  | NULL                | NULL    | NULL    | NULL  | 115282 | Using where; Using join buffer (flat, BNL join)        |
|    1 | SIMPLE      | pe    | ALL  | NULL                | NULL    | NULL    | NULL  | 120843 | Using where; Using join buffer (incremental, BNL join) |
|    1 | SIMPLE      | ph    | ref  | PRIMARY,date,date_2 | PRIMARY | 3       | const |      1 | Using where                                            |
+------+-------------+-------+------+---------------------+---------+---------+-------+--------+--------------------------------------------------------+

旧table #1 模式:

mysql> desc fiat.parts_warehouse_items;
+-----------------+--------------+------+-----+---------+-------+
| Field           | Type         | Null | Key | Default | Extra |
+-----------------+--------------+------+-----+---------+-------+
| itemno          | varchar(50)  | NO   | PRI |         |       |
| dataareaid      | varchar(10)  | NO   | PRI | NULL    |       |
| warehouseid     | varchar(20)  | NO   | PRI | NULL    |       |
| qoh             | int(11)      | YES  |     | NULL    |       |
| qty_avail       | int(11)      | YES  |     | NULL    |       |
| qty_posted      | int(11)      | YES  |     | NULL    |       |
| qty_received    | int(11)      | YES  |     | NULL    |       |
| qty_deducted    | int(11)      | YES  |     | NULL    |       |
| qty_picked      | int(11)      | YES  |     | NULL    |       |
| fifo_cost       | double(10,5) | YES  |     | NULL    |       |
| calculation     | text         | YES  |     | NULL    |       |
| method          | int(11)      | YES  |     | NULL    |       |
| qty_res_oh      | int(11)      | YES  |     | 0       |       |
| qty_avail_oh    | int(11)      | YES  |     | 0       |       |
| qty_ordrd       | int(11)      | YES  |     | 0       |       |
| qty_res_ordrd   | int(11)      | YES  |     | 0       |       |
| qty_avail_ordrd | int(11)      | YES  |     | 0       |       |
| qty_on_order    | int(11)      | YES  |     | 0       |       |
+-----------------+--------------+------+-----+---------+-------+

新table #1 架构:

mysql> desc lancia.warehouse_inventory;
+---------------------------+------------------------+------+-----+---------------------+----------------+
| Field                     | Type                   | Null | Key | Default             | Extra          |
+---------------------------+------------------------+------+-----+---------------------+----------------+
| id                        | int(11) unsigned       | NO   | PRI | NULL                | auto_increment |
| sku                       | varchar(20)            | NO   | MUL | NULL                |                |
| warehouse_id              | varchar(10)            | NO   |     | NULL                |                |
| site_id                   | varchar(10)            | NO   |     | NULL                |                |
| item_name                 | varchar(60)            | NO   |     | NULL                |                |
| item_color                | varchar(10)            | YES  |     | NULL                |                |
| item_config               | varchar(50)            | YES  |     | NULL                |                |
| item_size                 | varchar(10)            | YES  |     | NULL                |                |
| item_style                | varchar(10)            | YES  |     | NULL                |                |
| item_version              | varchar(10)            | YES  |     | NULL                |                |
| item_status               | varchar(10)            | NO   |     | NULL                |                |
| qty_onhand                | decimal(32,6) unsigned | NO   |     | 0.000000            |                |
| qty_onhand_reserved       | decimal(32,6) unsigned | NO   |     | 0.000000            |                |
| qty_onhand_available      | decimal(32,6) unsigned | NO   |     | 0.000000            |                |
| qty_ordered               | decimal(32,6) unsigned | NO   |     | 0.000000            |                |
| qty_ordered_reserved      | decimal(32,6) unsigned | NO   |     | 0.000000            |                |
| qty_ordered_available     | decimal(32,6) unsigned | NO   |     | 0.000000            |                |
| qty_on_order              | decimal(32,6) unsigned | NO   |     | 0.000000            |                |
| qty_total_available       | decimal(32,6)          | NO   |     | 0.000000            |                |
| warehouse_management_used | tinyint(1) unsigned    | NO   |     | 1                   |                |
| dataareaid                | varchar(4)             | NO   |     | NULL                |                |
| created_at                | timestamp              | NO   |     | current_timestamp() |                |
+---------------------------+------------------------+------+-----+---------------------+----------------+

是的。当您按相等连接时,ON 子句中两个表的两列应该精确地具有相同的数据类型、字符集和排序规则。排序规则被纳入索引。