首页 > 解决方案 > 为什么查询日期比查询 id 慢得多?

问题描述

我的应用程序需要两个 SQL 查询:

SELECT *
FROM a
LEFT JOIN b AS b1
ON a.source_id = b1.id AND a.source_type = 'xxxxx'
LEFT JOIN b AS b2
ON a.source_id = b2.id AND a.source_type = 'xxxxx'
WHERE (b1.user_id = 1 OR b2.user_id = 1);

解释给出以下内容:

|----|-------------|-------|------------|--------|----------------------------|---------|---------|----------------------|--------|----------|--------------------------------------------|

| id | select_type | table | partitions | type   | possible_keys              | key     | key_len | ref                  | rows   | filtered | Extra                                      |

|----|-------------|-------|------------|--------|----------------------------|---------|---------|----------------------|--------|----------|--------------------------------------------|

| 1  | SIMPLE      | a     | NULL       | ALL    | NULL                       | NULL    | NULL    | NULL                 | 437816 | 100.00   | NULL                                       |

|----|-------------|-------|------------|--------|----------------------------|---------|---------|----------------------|--------|----------|--------------------------------------------|

| 1  | SIMPLE      | b1    | NULL       | ALL    | PRIMARY                    | NULL    | NULL    | NULL                 | 6      | 100.00   | Using where; Using join buffer (hash join) |

|----|-------------|-------|------------|--------|----------------------------|---------|---------|----------------------|--------|----------|--------------------------------------------|

| 1  | SIMPLE      | b2    | NULL       | eq_ref | PRIMARY,index_b_on_user_id | PRIMARY | 8       | database.a.source_id | 1      | 100.00   | Using where                                |

|----|-------------|-------|------------|--------|----------------------------|---------|---------|----------------------|--------|----------|--------------------------------------------|

SELECT *
FROM a
LEFT JOIN b AS b1
ON a.source_id = b1.id AND a.source_type = 'xxxxx'
LEFT JOIN b AS b2
ON a.source_id = b2.id AND a.source_type = 'xxxxx'
WHERE (b1.date = '2021-03-09' OR b2.date = '2021-03-09');

解释给出以下

|----|-------------|-------|------------|--------|---------------|---------|---------|----------------------|--------|----------|--------------------------------------------|

| id | select_type | table | partitions | type   | possible_keys | key     | key_len | ref                  | rows   | filtered | Extra                                      |

|----|-------------|-------|------------|--------|---------------|---------|---------|----------------------|--------|----------|--------------------------------------------|

| 1  | SIMPLE      | a     | NULL       | ALL    | NULL          | NULL    | NULL    | NULL                 | 437816 | 100.00   | NULL                                       |

|----|-------------|-------|------------|--------|---------------|---------|---------|----------------------|--------|----------|--------------------------------------------|

| 1  | SIMPLE      | b1    | NULL       | ALL    | PRIMARY       | NULL    | NULL    | NULL                 | 6      | 100.00   | Using where; Using join buffer (hash join) |

|----|-------------|-------|------------|--------|---------------|---------|---------|----------------------|--------|----------|--------------------------------------------|

| 1  | SIMPLE      | b2    | NULL       | eq_ref | PRIMARY       | PRIMARY | 8       | database.a.source_id | 1      | 100.00   | Using where                                |

|----|-------------|-------|------------|--------|---------------|---------|---------|----------------------|--------|----------|--------------------------------------------|

指标如下:

|-------|------------|-----------------------------|--------------|-------------|-----------|-------------|----------|--------|------|------------|---------|---------------|---------|------------|

| Table | Non_unique | Key_name                    | Seq_in_index | Column_name | Collation | Cardinality | Sub_part | Packed | Null | Index_type | Comment | Index_comment | Visible | Expression |

|-------|------------|-----------------------------|--------------|-------------|-----------|-------------|----------|--------|------|------------|---------|---------------|---------|------------|

| b     | 0          | PRIMARY                     | 1            | id          | A         | 6           | NULL     | NULL   |      | BTREE      |         |               | YES     | NULL       |

|-------|------------|-----------------------------|--------------|-------------|-----------|-------------|----------|--------|------|------------|---------|---------------|---------|------------|

| b     | 1          | index_b_on_date_and_user_id | 1            | date        | A         | 5           | NULL     | NULL   | YES  | BTREE      |         |               | YES     | NULL       |

|-------|------------|-----------------------------|--------------|-------------|-----------|-------------|----------|--------|------|------------|---------|---------------|---------|------------|

| b     | 1          | index_b_on_date_and_user_id | 2            | user_id     | A         | 5           | NULL     | NULL   | YES  | BTREE      |         |               | YES     | NULL       |

|-------|------------|-----------------------------|--------------|-------------|-----------|-------------|----------|--------|------|------------|---------|---------------|---------|------------|

| b     | 1          | index_b_on_user_id          | 1            | user_id     | A         | 1           | NULL     | NULL   | YES  | BTREE      |         |               | YES     | NULL       |

|-------|------------|-----------------------------|--------------|-------------|-----------|-------------|----------|--------|------|------------|---------|---------------|---------|------------|

| b     | 1          | index_b_on_date             | 1            | date        | A         | 5           | NULL     | NULL   | YES  | BTREE      |         |               | YES     | NULL       |

|-------|------------|-----------------------------|--------------|-------------|-----------|-------------|----------|--------|------|------------|---------|---------------|---------|------------|

| a     | 0          | PRIMARY                     | 1            | id          | A         | 657         | NULL     | NULL   |      | BTREE      |         |               | YES     | NULL       |

|-------|------------|-----------------------------|--------------|-------------|-----------|-------------|----------|--------|------|------------|---------|---------------|---------|------------|

| a     | 1          | index_a_on_source_id        | 1            | source_id   | A         | 554         | NULL     | NULL   | YES  | BTREE      |         |               | YES     | NULL       |

|-------|------------|-----------------------------|--------------|-------------|-----------|-------------|----------|--------|------|------------|---------|---------------|---------|------------|

我知道这些查询并没有真正的意义,因为它们在相同的数据上加入了同一个表,但这是一个更大查询的简化版本,它仍然表现出相同的行为。

带有日期的第一个查询在 0.0021 秒内运行,但是第二个在大约 2 秒内运行。我想知道为什么两个相似的查询之间存在如此大的差异,如果可能的话,我想改进错误的查询。b两者都有索引datecompany_id所以我很难看出除了数据类型之外的差异来自哪里。

我在使用查询时注意到的一件有趣的事情是,如果我OR从第二个查询中删除它,它就会变成:

SELECT *
FROM a
LEFT JOIN b AS b1
ON a.source_id = b1.id AND a.source_type = 'xxxxx'
LEFT JOIN b AS b2
ON a.source_id = b2.id AND a.source_type = 'xxxxx'
WHERE b1.date = '2021-03-09';

那么执行只需要 0.00055 秒。

标签: mysqlsql

解决方案


推荐阅读