【问题标题】:LEFT JOIN slows performance by about a hundred timesLEFT JOIN 会使性能降低大约一百倍
【发布时间】:2022-11-16 08:37:26
【问题描述】:

查询 1 - 没有 LEFT JOIN:

SELECT 
  COUNT(r.id)

FROM requests r

WHERE r.deleted = 0
AND r.req_status_id = 'processed'

执行时间 = 0.012 秒。

解释结果:

{
  "query_block": {
    "select_id": 1,
    "cost_info": {
      "query_cost": "4335.28"
    },
    "table": {
      "table_name": "r",
      "access_type": "ref",
      "possible_keys": [
        "requests_idx55",
        "req_status_id_2",
        "req_status_id"
      ],
      "key": "req_status_id_2",
      "used_key_parts": [
        "deleted",
        "req_status_id"
      ],
      "key_length": "387",
      "ref": [
        "const",
        "const"
      ],
      "rows_examined_per_scan": 17504,
      "rows_produced_per_join": 17504,
      "filtered": "100.00",
      "using_index": true,
      "cost_info": {
        "read_cost": "834.48",
        "eval_cost": "3500.80",
        "prefix_cost": "4335.28",
        "data_read_per_join": "122M"
      },
      "used_columns": [
        "id",
        "req_status_id",
        "deleted"
      ]
    }
  }
}

requests信息:

  • ~300万条记录
  • deleted 列:索引(索引名称为requests_idx55),数据类型 - 位 (1)
  • req_status_id 列:索引,数据类型 - varchar(128)
  • contract_cat_id 列:索引,数据类型 - int(10) 无符号

查询 2 - 使用 LEFT JOIN:

SELECT 
   COUNT(r.id)

FROM requests r

LEFT JOIN wt_contracts_cats wcc
ON r.contract_cat_id = wcc.id

WHERE r.deleted = 0
AND r.req_status_id = 'processed'

执行时间 = 0.9-1.1 秒。

解释结果:

{
  "query_block": {
    "select_id": 1,
    "cost_info": {
      "query_cost": "25840.54"
    },
    "nested_loop": [
      {
        "table": {
          "table_name": "r",
          "access_type": "index_merge",
          "possible_keys": [
            "requests_idx55",
            "req_status_id_2",
            "req_status_id"
          ],
          "key": "intersect(req_status_id,requests_idx55)",
          "key_length": "386,1",
          "rows_examined_per_scan": 10125,
          "rows_produced_per_join": 10125,
          "filtered": "100.00",
          "cost_info": {
            "read_cost": "11665.54",
            "eval_cost": "2025.00",
            "prefix_cost": "13690.54",
            "data_read_per_join": "70M"
          },
          "used_columns": [
            "id",
            "req_status_id",
            "contract_cat_id",
            "deleted"
          ],
          "attached_condition": "((`atm`.`r`.`deleted` = 0) and (`atm`.`r`.`req_status_id` = 'processed'))"
        }
      },
      {
        "table": {
          "table_name": "wcc",
          "access_type": "eq_ref",
          "possible_keys": [
            "PRIMARY"
          ],
          "key": "PRIMARY",
          "used_key_parts": [
            "id"
          ],
          "key_length": "4",
          "ref": [
            "atm.r.contract_cat_id"
          ],
          "rows_examined_per_scan": 1,
          "rows_produced_per_join": 10125,
          "filtered": "100.00",
          "using_index": true,
          "cost_info": {
            "read_cost": "10125.00",
            "eval_cost": "2025.00",
            "prefix_cost": "25840.54",
            "data_read_per_join": "15M"
          },
          "used_columns": [
            "id"
          ]
        }
      }
    ]
  }
}

wt_contracts_cats信息:

  • ~15 000 条记录
  • id 列:主索引,数据类型 - int(10) 无符号

我试图理解为什么它会这样工作,研究了 EXPLAIN 的结果,但找不到这种行为的任何原因。

谁能解释为什么会这样?

【问题讨论】:

    标签: mysql left-join


    【解决方案1】:

    它无缘无故地进入另一张桌子。如果您不打算使用其他表中的任何内容,为什么要对另一个表执行 LEFT JOIN

    我认为 MySQL Optimizer 决定没有人会费心去做这样的思考所以它也懒得去 Optimizer 出来。 (玛丽亚数据库进行优化。)此外,如果它被埋在 VIEW 中,那么即使是细心的程序员有时也会创建不必要的 LEFT JOIN

    在 bugs.mysql.com 提交错误报告。

    【讨论】:

      猜你喜欢
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 2016-02-25
      • 1970-01-01
      • 2021-04-05
      • 2012-03-08
      • 2019-01-28
      • 1970-01-01
      相关资源
      最近更新 更多