【发布时间】:2016-10-02 14:09:34
【问题描述】:
我对一些奇怪的 mysql 性能行为感到非常惊讶。我的以下查询需要大约 3 个小时才能运行:
UPDATE ips_invoice AS f SET ips_locality_id = (
SELECT ips_locality_id
FROM ips_user_unit_locality AS uul
JOIN ips_user AS u ON u.id = uul.ips_user_id
WHERE
(u.id = f.ips_user_id OR u.ips_user_id_holder = f.ips_user_id) AND
uul.date <= f.date
ORDER BY `date` DESC
LIMIT 1
)
WHERE f.ips_locality_id IS NULL;
我也尝试了以下一种,但得到了相同的性能结果:
UPDATE ips_invoice AS f SET ips_locality_id = (
SELECT ips_locality_id
FROM ips_user_unit_locality AS uul
JOIN ips_user AS u ON u.id = uul.ips_user_id
WHERE
IFNULL(u.ips_user_id_holder, u.id) = f.ips_user_id
AND
uul.date <= f.date
ORDER BY `date` DESC
LIMIT 1
)
WHERE f.ips_locality_id IS NULL;
逻辑是:如果“ips_user_id_holder”列不为空,我应该使用它,如果不是,我应该使用“id”列。
如果我将查询拆分为两个查询,每个查询需要 15 秒才能运行:
UPDATE ips_invoice AS f SET ips_locality_id = (
SELECT ips_locality_id
FROM ips_user_unit_locality AS uul
JOIN ips_user AS u ON u.id = uul.ips_user_id
WHERE
u.ips_user_id_holder = f.ips_user_id
AND
uul.date <= f.date
ORDER BY `date` DESC
LIMIT 1
)
WHERE f.ips_locality_id IS NULL;
UPDATE ips_invoice AS f SET ips_locality_id = (
SELECT ips_locality_id
FROM ips_user_unit_locality AS uul
JOIN ips_user AS u ON u.id = uul.ips_user_id
WHERE
u.id = f.ips_user_id
AND
uul.date <= f.date
ORDER BY `date` DESC
LIMIT 1
)
WHERE f.ips_locality_id IS NULL;
这不是我第一次遇到 Mysql “OR” 或 “null checks” 的问题 相对简单的查询 (Why this mysql query (with is null check) is so slower than this other one?)。
ips_invoice 表有大约 400.000 条记录,ips_user_unit_locality 大约有 100.000 条记录,ips_user 大约有 35.000 条记录。
我在 Ubuntu Amazon EC2 实例中运行 MySQL 5.5.49。
那么,第一个和第二个查询有什么问题?造成显着性能差异的原因是什么?
【问题讨论】:
标签: mysql sql performance