DATE()导致SQL查询占用太长时间

时间:2013-11-19 08:32:24

标签: mysql sql

我正在运行一个超过5分钟的查询以产生结果。当我将LEFT JOIN中的DATE(NOW)更改为一列时需要9秒。以下是显示更快线的查询

SELECT DISTINCT(rental.id), filmCopy.location fC_id, member.id m_id, filmInfo.title fI_title, member.name, member.surname, member.cellphone, member.telephone, rental.due_back,rental.returned, filmCopy.on_loan_to, filmInfo.folder fI_folder, reservation_date rsrvtn, reservation.id res_id
FROM rental
INNER JOIN transactionSummary ON transactionSummary.id = rental.transactionSummary_id
INNER JOIN member ON member.id = transactionSummary.member_id
INNER JOIN filmCopy ON filmCopy.id = rental.filmCopy_id
INNER JOIN filmInfo ON filmInfo.id = filmCopy.filmInfo_id
INNER JOIN filmPriceBracket ON filmPriceBracket.filmInfo_id = filmInfo.id
AND filmPriceBracket.filmCopytype_id = filmCopy.filmCopyType_id
LEFT JOIN reservation ON reservation.filmInfo_id = filmInfo.id
  

快得多 - LEFT JOIN预约ON reservation.filmInfo_id = filmInfo.id AND   reservation.reservation_date = DATE(rental.due_back)

AND reservation.reservation_date = DATE(NOW())
WHERE rental.due_back < DATE_SUB(NOW(), INTERVAL 1 DAY)
AND rental.returned IS NULL 
AND filmPriceBracket.filmCopyType_id !=24
AND filmPriceBracket.filmCopyType_id !=23
ORDER BY  fI_folder, rsrvtn DESC, filmCopy_id, rental.due_back

慢速查询给了我正确的结果,因为快速的一个是好的但不完整。 关于为什么使用今天DATE的任何建议都会让它变得如此缓慢?

对于背景信息,它会提取过期电影的报告以及保留(过期和未过期) 感谢

修改


这是我从下面的答案中得到的结果,但是语法中出现错误..

DECLARE @NOW DATE
SELECT @NOW := DATE(NOW())

SELECT DISTINCT(rental.id), filmCopy.location fC_id, member.id m_id, filmInfo.title fI_title, member.name, member.surname, member.cellphone, member.telephone, rental.due_back,rental.returned, filmCopy.on_loan_to, filmInfo.folder fI_folder, reservation_date rsrvtn, reservation.id res_id
FROM rental    
INNER JOIN transactionSummary ON transactionSummary.id = rental.transactionSummary_id
INNER JOIN member ON member.id = transactionSummary.member_id
INNER JOIN filmCopy ON filmCopy.id = rental.filmCopy_id
INNER JOIN filmInfo ON filmInfo.id = filmCopy.filmInfo_id
INNER JOIN filmPriceBracket ON filmPriceBracket.filmInfo_id = filmInfo.id
AND filmPriceBracket.filmCopytype_id = filmCopy.filmCopyType_id
LEFT JOIN reservation ON reservation.filmInfo_id = filmInfo.id
AND reservation.reservation_date = @NOW 
WHERE $where 
AND rental.returned IS NULL 
AND filmPriceBracket.filmCopyType_id !=24
AND filmPriceBracket.filmCopyType_id !=23
ORDER BY  fI_folder, rsrvtn DESC, filmCopy_id, rental.due_back

3 个答案:

答案 0 :(得分:2)

您可以尝试首先创建包含DATE(NOW())DATE_SUB(...)值的两个变量,这样就不必为每条记录评估它们。


这样的事情应该在MySQL中做到:

DECLARE @NOW DATE;
DECLARE @YESTERDAY DATE;

SELECT @NOW := DATE(NOW());
SELECT @YESTERDAY := DATE_SUB(@NOW, INTERVAL 1 DAY);

...
AND reservation.reservation_date = @NOW
WHERE rental.due_back < @YESTERDAY
...

答案 1 :(得分:0)

首先验证两个查询确实返回相同数量的行(我曾经多次咬过这个行)。

然后,您可以通过执行来避免对每行进行DATE(NOW())评估 - 这是MySQL语法;你没有说你正在使用什么数据库 -

SELECT @DATENOW:=DATE(NOW());
SELECT @DATESUB:=DATE_SUB(NOW(), INTERVAL 1 DAY)

并使用@DATENOW@DATESUB代替DATE(NOW())DATE_SUB(NOW(), INTERVAL 1 DAY)

通常,您希望所有生成常量或几乎常量的表达式(在查询期间NOW()实际变化)显式为常量。如果您可以以编程方式构建查询,也可以执行此应用程序端:

# very pseudo code
query := 'SELECT ... ' + date_format(...) + '...'
run_query( query )

答案 2 :(得分:0)

通过编写reservation.reservation_date = DATE(NOW()),您为每个满足在where子句上定义的过滤器的记录调用NOW()函数,这是您的SQL代码的瓶颈。

你可以为DATE(NOW())条件定义一个变量并改为使用它。

注意:如果您使用的是oracle系统,可以使用 with 子句传递变量