mysql - 为什么查询日期比查询 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
两者都有索引date
,company_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 秒。
解决方案
推荐阅读
- bash - 如果一列中的值包含连续数字并且所有其他列匹配,如何合并行
- java - Android XML-Java 更改首选项的背景颜色
- ios - Xcode Storyboard:根据屏幕大小重新调整按钮大小
- html - 在 CSS 中使图像适合 flexbox 容器
- reactjs - 默认情况下显示第一个 React-leaflet 弹出窗口
- java - 使用 Java 对 API 进行 HTTPS 调用
- image-processing - 只有在整个对象完全在感兴趣区域内之后,如何放置边界框?
- http - 为单个 HTTP 请求返回多个文件的最佳实践?
- shopify - 无法在 Shopify LIquid 中连接两个值
- java - 将 1.8 Maven 项目更改为编译为 1.16 会产生“无效的目标版本 1.16”