我在 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必须遍历子集中的所有值)。
有人有更好的推理能力还是反正可以改善此查询?
答案 0 :(得分:2)
打开
NOT IN ( SELECT ... )
融入其中
NOT EXISTS ( SELECT ... )
或
LEFT JOIN ... WHERE .. IS NULL
然后查看是否可以摆脱更多子查询。
如果这些都不够快,我会再看。
可能的原因是MariaDB具有MySQL不具备的功能:子查询缓存。此外,MySQL在5.5之后具有3个主要版本,并且在其中进行了一些重大的优化改进。
从每个服务器上看到SHOW VARIABLES
和SHOW GLOBAL STATUS
(加上RAM大小)会很有趣。由此,我认为我可以指出正在使用缓存。
与此同时,我在重新编写建议中的目标是加快MySQL(也许还有MariaDB)的速度。
答案 1 :(得分:0)
override fun onActivityCreated(savedInstanceState: Bundle?) {
super.onActivityCreated(savedInstanceState)
val viewModel = viewDataBinding.viewmodel
viewModel?.login()?.observe(this.activity, Observer {
Log.d(TAG, it?.email)
})
}