与Mariadb 10.2相比,Mysql 5.5中的查询非常慢

时间:2018-08-06 12:36:48

标签: mysql mariadb

我在 Mysql 5.5 Mariadb 10.2 中运行了以下查询。在Mariadb中运行查询只花了 4秒,而在Mysql中花了 6分钟

SELECT
  ' ' AS max_claim_amount,
  claims_only_A.*
FROM
  (
    SELECT
      employee.emp_number AS emp_number,
      ' ' AS emp_id,
      ' ' AS emp_name,
      NULL AS estimate_id,
      NULL AS estimate_submitted_date,
      NULL AS estimate_state,
      NULL AS currency_for_reimbursement,
      NULL AS cash_in_advance,
      NULL AS estimate_purpose,
      NULL AS estimate_exp_type,
      NULL AS estimate_foreign_currency,
      NULL AS estimate_exchange_rate,
      NULL AS estimate_amount,
      NULL AS claim_id,
      NULL AS claim_currency_for_reimbursement,
      NULL AS claimed_date,
      NULL AS claim_exp_type,
      cety.id AS claim_exp_type_id,
      claim_cc.currency_id AS claim_foreign_currency,
      cex.exchange_rate AS claim_exchange_rate,
      cex.amount AS claim_amount,
      cex.remarks AS claim_remarks,
      employee.deleted_at AS emp_deleted_at,
      employee.purged_at AS emp_purged_at,
      employee.termination_id AS emp_termination_id,
      employee.emp_lastname AS emp_lastname,
      el.location_id AS emp_location_id,
      employee.job_title_code AS emp_job_title_code,
      employee.work_station AS emp_work_station,
      cr.request_id AS claim_request_id,
      employee.emp_status AS emp_status,
      NULL AS estimate_sort_id,
      cex.id AS claim_exp_id
    FROM
      `claim_request` cr
      LEFT JOIN `claim_expense` cex ON cex.request_id = cr.id
      LEFT JOIN `claim_expense_type` cety ON cex.expense_type_id = cety.id
      LEFT JOIN `_employee` AS employee ON cr.emp_number = employee.emp_number
      LEFT JOIN claim_currency claim_cc ON (claim_cc.id = cex.currency_id)
      LEFT JOIN claim_currency claim_req_cc ON (claim_req_cc.id = cr.currency_id)
      LEFT JOIN _emp_locations el ON(employee.emp_number = el.emp_number)
    WHERE
      cr.id NOT IN (
        SELECT
          claim_request_id
        FROM
          `claim_estimation_claiming`
      )
  ) AS claims_only_A
WHERE
  (claim_request_id, claim_amount) NOT IN (
    SELECT
      claim_request_id,
      MAX(claim_amount)
    FROM
      (
        SELECT
          cr.request_id AS claim_request_id,
          cex.amount AS claim_amount,
          cety.name AS claim_expense_type,
          cex.id AS claim_exp_id
        FROM
          `claim_request` cr
          LEFT JOIN `claim_expense` cex ON cex.request_id = cr.id
          LEFT JOIN `claim_expense_type` cety ON cex.expense_type_id = cety.id
        WHERE
          cr.id NOT IN (
            SELECT
              claim_request_id
            FROM
              `claim_estimation_claiming`
          )
      ) AS A
    GROUP BY
      claim_request_id,
      claim_expense_type
  )

查询运行的说明如下

-- MYSQL 5.5
+----+--------------------+--------------------------------+----------------+------------------+------------------+---------+-----------------------------------------+------+---------------------------------+
| id | select_type        | table                          | type           | possible_keys    | key              | key_len | ref                                     | rows | Extra                           |
+----+--------------------+--------------------------------+----------------+------------------+------------------+---------+-----------------------------------------+------+---------------------------------+
|  1 | PRIMARY            | <derived2>                     | ALL            | NULL             | NULL             | NULL    | NULL                                    | 2876 | Using where                     |
|  4 | DEPENDENT SUBQUERY | <derived5>                     | ALL            | NULL             | NULL             | NULL    | NULL                                    | 2876 | Using temporary; Using filesort |
|  5 | DERIVED            | cr                             | ALL            | NULL             | NULL             | NULL    | NULL                                    | 1131 | Using where                     |
|  5 | DERIVED            | cex                            | ref            | request_id       | request_id       | 5       | dbname.cr.id               |    1 |                                 |
|  5 | DERIVED            | cety                           | eq_ref         | PRIMARY          | PRIMARY          | 4       | dbname.cex.expense_type_id |    1 |                                 |
|  6 | DEPENDENT SUBQUERY | claim_estimation_claiming | index_subquery | claim_request_id | claim_request_id | 5       | func                                    |    2 | Using index                     |
|  2 | DERIVED            | cr                             | ALL            | NULL             | NULL             | NULL    | NULL                                    | 1131 | Using where                     |
|  2 | DERIVED            | cex                            | ref            | request_id       | request_id       | 5       | dbname.cr.id               |    1 |                                 |
|  2 | DERIVED            | cety                           | eq_ref         | PRIMARY          | PRIMARY          | 4       | dbname.cex.expense_type_id |    1 | Using index                     |
|  2 | DERIVED            | employee                       | eq_ref         | PRIMARY          | PRIMARY          | 4       | dbname.cr.emp_number       |    1 |                                 |
|  2 | DERIVED            | claim_cc                       | eq_ref         | PRIMARY          | PRIMARY          | 4       | dbname.cex.currency_id     |    1 |                                 |
|  2 | DERIVED            | claim_req_cc                   | eq_ref         | PRIMARY          | PRIMARY          | 4       | dbname.cr.currency_id      |    1 | Using index                     |
|  2 | DERIVED            | el                             | ref            | PRIMARY          | PRIMARY          | 4       | dbname.employee.emp_number |    1 | Using index                     |
|  3 | DEPENDENT SUBQUERY | claim_estimation_claiming | index_subquery | claim_request_id | claim_request_id | 5       | func                                    |    2 | Using index                     |
+----+--------------------+--------------------------------+----------------+------------------+------------------+---------+-----------------------------------------+------+---------------------------------+

-- MARIADB 10.2
+------+--------------+--------------------------------+--------+------------------+------------------+---------+-----------------------------------------+------+------------------------------+
| id   | select_type  | table                          | type   | possible_keys    | key              | key_len | ref                                     | rows | Extra                        |
+------+--------------+--------------------------------+--------+------------------+------------------+---------+-----------------------------------------+------+------------------------------+
|    1 | PRIMARY      | cr                             | ALL    | NULL             | NULL             | NULL    | NULL                                    |  920 | Using where                  |
|    1 | PRIMARY      | cex                            | ref    | request_id       | request_id       | 5       | dbname.cr.id               |    1 | Using where                  |
|    1 | PRIMARY      | cety                           | eq_ref | PRIMARY          | PRIMARY          | 4       | dbname.cex.expense_type_id |    1 | Using where; Using index     |
|    1 | PRIMARY      | employee                       | eq_ref | PRIMARY          | PRIMARY          | 4       | dbname.cr.emp_number       |    1 | Using where                  |
|    1 | PRIMARY      | claim_cc                       | eq_ref | PRIMARY          | PRIMARY          | 4       | dbname.cex.currency_id     |    1 | Using where                  |
|    1 | PRIMARY      | el                             | ref    | PRIMARY          | PRIMARY          | 4       | dbname.employee.emp_number |    1 | Using where; Using index     |
|    4 | MATERIALIZED | cr                             | ALL    | NULL             | NULL             | NULL    | NULL                                    |  920 | Using where; Using temporary |
|    4 | MATERIALIZED | cex                            | ref    | request_id       | request_id       | 5       | dbname.cr.id               |    1 |                              |
|    4 | MATERIALIZED | cety                           | eq_ref | PRIMARY          | PRIMARY          | 4       | dbname.cex.expense_type_id |    1 | Using where                  |
|    6 | MATERIALIZED | claim_estimation_claiming | index  | claim_request_id | claim_request_id | 5       | NULL                                    |    1 | Using index                  |
|    3 | MATERIALIZED | claim_estimation_claiming | index  | claim_request_id | claim_request_id | 5       | NULL                                    |    1 | Using index                  |
+------+--------------+--------------------------------+--------+------------------+------------------+---------+-----------------------------------------+------+------------------------------+

我尝试单独运行子查询,但子查询在Mysql中没有显示任何延迟。问题似乎仅在查询整体运行时发生。

据我所知,根据解释,问题似乎是因为Mysql 5.5在type字段中具有更多All值(这意味着mysql必须遍历子集中的所有值)。

有人有更好的推理能力还是反正可以改善此查询?

2 个答案:

答案 0 :(得分:2)

打开

NOT IN ( SELECT ... )

融入其中

NOT EXISTS ( SELECT ... )

LEFT JOIN ... WHERE .. IS NULL

然后查看是否可以摆脱更多子查询。

如果这些都不够快,我会再看。

可能的原因是MariaDB具有MySQL不具备的功能:子查询缓存。此外,MySQL在5.5之后具有3个主要版本,并且在其中进行了一些重大的优化改进。

从每个服务器上看到SHOW VARIABLESSHOW GLOBAL STATUS(加上RAM大小)会很有趣。由此,我认为我可以指出正在使用缓存。

与此同时,我在重新编写建议中的目标是加快MySQL(也许还有MariaDB)的速度。

答案 1 :(得分:0)

  1. 好像有一个多余的左联接,该联接在任何地方都没有使用,因此删除它会很有帮助:override fun onActivityCreated(savedInstanceState: Bundle?) { super.onActivityCreated(savedInstanceState) val viewModel = viewDataBinding.viewmodel viewModel?.login()?.observe(this.activity, Observer { Log.d(TAG, it?.email) }) }
  2. 如Rick所述,尝试将NOT IN修改为NOT EXISTS。