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 

DB FIDDLE HERE WITH STRUCTURE

请试试这个,如果有效...将通过添加复合索引进一步优化。

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_logsreturn_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;

毕竟,我们可能需要另一遍来进一步简化和优化它。