Запрос в Mysql 5.5 очень медленный по сравнению с Mariadb 10.2

0

Я выполнил следующий запрос в Mysql 5.5 и Mariadb 10.2. для выполнения запроса в Мариадбе потребовалось всего 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 имеет больше значений All в поле type (это означает, что mysql должен пройти все значения в подмножестве).

У кого-нибудь есть лучшая аргументация или В любом случае, чтобы улучшить этот запрос?

  • 0
    Это очень сложный запрос, и большинству читателей может быть трудно сделать содержательное предложение. Если вы можете сократить запрос до чего-то более простого, что все еще демонстрирует разницу между MySQL и MariaDB, это может помочь вам быстрее получить ответ.
Теги:
mariadb

2 ответа

2

Очередь

NOT IN ( SELECT ... )

в

NOT EXISTS ( SELECT ... )

или же

LEFT JOIN ... WHERE .. IS NULL

Затем посмотрите, можете ли вы избавиться от большего количества подзапросов.

Если они не ускорят его, я снова посмотрю.

Вероятная причина заключается в том, что у MariaDB есть функция, которой MySQL не обладает: кэширование подзапросов. Кроме того, MySQL имеет 3 основных версии после 5.5, и в них есть некоторые значительные улучшения оптимизации.

Было бы интересно увидеть SHOW VARIABLES и SHOW GLOBAL STATUS с каждого сервера (плюс размер RAM). Из этого, я думаю, я могу указать, что кеширование используется.

Между тем, моя цель в предложениях по переформулированию - ускорить работу MySQL (и, возможно, MariaDB).

0
  1. Похоже, есть избыточное левое соединение, которое нигде не используется, поэтому будет полезно удалить его: claim_req_cc
  2. Попробуйте изменить NOT IN, чтобы НЕ СУЩЕСТВОВАТЬ, как упомянул Рик.

Ещё вопросы

Сообщество Overcoder
Наверх
Меню