JOIN 查询花费很长时间并产生问题“将 HEAP 转换为 MyISAM
JOIN query taking long time and creating issue "converting HEAP to MyISAM
我的查询如下。这里我使用连接查询来获取数据。你能建议我如何解决 "converting HEAP to MyISAM" 问题吗?
我可以在这里使用子查询来更新它吗?请建议我该怎么做。
这里我加入了用户table来检查用户是否存在。我可以在不加入的情况下对其进行优化,以便 "converting HEAP to MyISAM" 可以解决吗?
哦,有时候我不会检查具体user_id。就像这里我添加了 user_id = 16082
SELECT `user_point_logs`.`id`,
`user_point_logs`.`user_id`,
`user_point_logs`.`point_get_id`,
`user_point_logs`.`point`,
`user_point_logs`.`expire_date`,
`user_point_logs`.`point` AS `sum_point`,
IF(sum(`user_point_used_logs`.`point`) IS NULL, 0, sum(`user_point_used_logs`.`point`)) AS `minus`
FROM `user_point_logs`
JOIN `users` ON ( `users`.`id` = `user_point_logs`.`user_id` )
LEFT JOIN (SELECT *
FROM user_point_used_logs
WHERE user_point_log_id NOT IN (
SELECT DISTINCT return_id
FROM user_point_logs
WHERE return_id IS NOT NULL
AND user_id = 16082
)
)
AS user_point_used_logs
ON ( `user_point_logs`.`id` = `user_point_used_logs`.`user_point_log_used_id` )
WHERE expire_date >= 1563980400
AND `user_point_logs`.`point` >= 0
AND `users`.`id` IS NOT NULL
AND ( `user_point_logs`.`return_id` = 0
OR `user_point_logs`.`return_id` IS NULL )
AND `user_point_logs`.`user_id` = '16082'
GROUP BY `user_point_logs`.`id`
ORDER BY `user_point_logs`.`expire_date` ASC
请试试这个,如果有效...将通过添加复合索引进一步优化。
SELECT
upl.id,
upl.user_id,
upl.point_get_id,
upl.point,
upl.expire_date,
upl.point AS sum_point,
coalesce(SUM(upl.point),0) AS minus -- changed from complex to readable
FROM user_point_logs upl
JOIN users u ON upl.user_id = u.id
LEFT JOIN (select supul.user_point_log_used_id from user_point_used_logs supul
left join user_point_logs supl on supul.user_point_log_id=supl.return_id and supl.return_id is null and supl.user_id = 16082) AS upul
ON upl.id=upul.user_point_log_used_id
WHERE
upl.user_id = 16082 and coalesce(upl.return_id,0)= 0
and upl.expire_date >= 1563980400 -- tip: if its unix timestamp change the datatype and if possible use range between dates
#AND upl.point >= 0 -- since its NN by default removing this condition
#AND u.id IS NOT NULL -- removed since the inner join matches not null
GROUP BY upl.id
ORDER BY upl.expire_date ASC;
编辑:
尝试在 table user_point_logs
的 return_id
列中添加索引。
由于此列用于连接派生查询。
或者使用 user_id and return_id
的复合索引
索引:
user_point_logs: (user_id, expire_date)
user_point_logs: (user_id, return_id)
OR
很难优化。决定只用一种方式来表达这里所说的一切,然后去掉 OR
:
AND ( `user_point_logs`.`return_id` = 0
OR `user_point_logs`.`return_id` IS NULL )
DISTINCT
是多余的:
NOT IN ( SELECT DISTINCT ... )
改变
IF(sum(`user_point_used_logs`.`point`) IS NULL, 0,
sum(`user_point_used_logs`.`point`)) AS `minus`
至
COALESCE( ( SELECT SUM(point) FROM user_point_used_logs ... ), 0) AS minus
并投掷 LEFT JOIN (SELECT * FROM user_point_used_logs ... )
因为 PRIMARY KEY
是一个键,第二个是多余的,可以是 DROPped
:
ADD PRIMARY KEY (`id`),
ADD KEY `id` (`id`) USING BTREE;
毕竟,我们可能需要另一遍来进一步简化和优化它。
我的查询如下。这里我使用连接查询来获取数据。你能建议我如何解决 "converting HEAP to MyISAM" 问题吗?
我可以在这里使用子查询来更新它吗?请建议我该怎么做。
这里我加入了用户table来检查用户是否存在。我可以在不加入的情况下对其进行优化,以便 "converting HEAP to MyISAM" 可以解决吗?
哦,有时候我不会检查具体user_id。就像这里我添加了 user_id = 16082
SELECT `user_point_logs`.`id`,
`user_point_logs`.`user_id`,
`user_point_logs`.`point_get_id`,
`user_point_logs`.`point`,
`user_point_logs`.`expire_date`,
`user_point_logs`.`point` AS `sum_point`,
IF(sum(`user_point_used_logs`.`point`) IS NULL, 0, sum(`user_point_used_logs`.`point`)) AS `minus`
FROM `user_point_logs`
JOIN `users` ON ( `users`.`id` = `user_point_logs`.`user_id` )
LEFT JOIN (SELECT *
FROM user_point_used_logs
WHERE user_point_log_id NOT IN (
SELECT DISTINCT return_id
FROM user_point_logs
WHERE return_id IS NOT NULL
AND user_id = 16082
)
)
AS user_point_used_logs
ON ( `user_point_logs`.`id` = `user_point_used_logs`.`user_point_log_used_id` )
WHERE expire_date >= 1563980400
AND `user_point_logs`.`point` >= 0
AND `users`.`id` IS NOT NULL
AND ( `user_point_logs`.`return_id` = 0
OR `user_point_logs`.`return_id` IS NULL )
AND `user_point_logs`.`user_id` = '16082'
GROUP BY `user_point_logs`.`id`
ORDER BY `user_point_logs`.`expire_date` ASC
请试试这个,如果有效...将通过添加复合索引进一步优化。
SELECT
upl.id,
upl.user_id,
upl.point_get_id,
upl.point,
upl.expire_date,
upl.point AS sum_point,
coalesce(SUM(upl.point),0) AS minus -- changed from complex to readable
FROM user_point_logs upl
JOIN users u ON upl.user_id = u.id
LEFT JOIN (select supul.user_point_log_used_id from user_point_used_logs supul
left join user_point_logs supl on supul.user_point_log_id=supl.return_id and supl.return_id is null and supl.user_id = 16082) AS upul
ON upl.id=upul.user_point_log_used_id
WHERE
upl.user_id = 16082 and coalesce(upl.return_id,0)= 0
and upl.expire_date >= 1563980400 -- tip: if its unix timestamp change the datatype and if possible use range between dates
#AND upl.point >= 0 -- since its NN by default removing this condition
#AND u.id IS NOT NULL -- removed since the inner join matches not null
GROUP BY upl.id
ORDER BY upl.expire_date ASC;
编辑:
尝试在 table user_point_logs
的 return_id
列中添加索引。
由于此列用于连接派生查询。
或者使用 user_id and return_id
索引:
user_point_logs: (user_id, expire_date)
user_point_logs: (user_id, return_id)
OR
很难优化。决定只用一种方式来表达这里所说的一切,然后去掉 OR
:
AND ( `user_point_logs`.`return_id` = 0
OR `user_point_logs`.`return_id` IS NULL )
DISTINCT
是多余的:
NOT IN ( SELECT DISTINCT ... )
改变
IF(sum(`user_point_used_logs`.`point`) IS NULL, 0,
sum(`user_point_used_logs`.`point`)) AS `minus`
至
COALESCE( ( SELECT SUM(point) FROM user_point_used_logs ... ), 0) AS minus
并投掷 LEFT JOIN (SELECT * FROM user_point_used_logs ... )
因为 PRIMARY KEY
是一个键,第二个是多余的,可以是 DROPped
:
ADD PRIMARY KEY (`id`),
ADD KEY `id` (`id`) USING BTREE;
毕竟,我们可能需要另一遍来进一步简化和优化它。