2015-10-14 97 views
0

我正在计算一个大型数据库中两个日期之间的营业时间,它正在工作。 但是这个请求很长,因为有很多选择。 我想优化它,但似乎我不能使用别名。 任何想法?如何在另一次选择中多次重复选择时进行优化?

这里是我的问题的看法:

我有一个第一次约会:选择A:

SELECT CASE 
WHEN (... = 9) 
THEN (SELECT ...) 
     ELSE (SELECT ... FROM ... 
     WHERE ((...) AND (...) AND 
     ((...='1' OR ...'10009' OR ...='10011') AND ...='3')) 
     ) 
    END 
    FROM ... 

和我的第二个日期:SELECT B:

SELECT 
    CASE 
     WHEN (...) AND ... 
     THEN( SELECT ... FROM ... 
       WHERE ((... 
       AND (...) AND (...) 
       AND (...)) ) 
     WHEN (...) AND ... 
     THEN( SELECT ... FROM ... 
       WHERE (...) AND ... AND ... AND ... AND ...) 
     ELSE NULL 
    END 
) 

然后我将它们复制在下面的查询中(这是在另一个大查询中......对于具有多列的报告):

SELECT (TIMESTAMPDIFF(MINUTE, GetBusinessHours(SELECT A),GetBusinessHours(SELECT B)) 
- 13*60*DATEDIFF(GetBusinessHours(SELECT B) , GetBusinessHours(SELECT A)) 
- 2*11*60*(WEEK(SELECT B) - WEEK(SELECT A)) 
- SELECT COUNT(*) FROM X WHERE DATE BETWEEN ((SELECT A) AND (SELECT B)) 

因此,这最后一个查询变得巨大,它需要70行。有没有一种方法来优化事实,我不必重新计算每个SELECT A和SELECT B 4次?

+0

使用'explain'来准确指出它的速度慢。不要一直计算结果,缓存它(或实现它)。剩下的事情就是创建一个事件,根据间隔时间为你预先计算这个事件,这样你的应用程序就可以读取数据了(它总是很快)。在解释输出到达之前,我们可以推测什么确实很慢。由于这是一个很大的数据库,我怀疑还有一些繁重的磁盘寻找,我们通过为此目的分配RAM来避免。 – Mjh

+0

谢谢。 我检查了解释并看到100000+行10次。它位于我的SELECT A或B之一的依赖子查询中,但这些行与其他行不同。 类型是索引,possible_keys是空的,ref是空的并且在Extra:using索引中说。 我会检查它的确切位置,并尝试从所有脚本中提取。 –

+0

好吧,它正在进行全表扫描。发布表结构,解释和精确查询的确切输出将有所帮助,但似乎您正在使用表的全部内容来计算营业时间。这涉及到磁盘寻道,因为你可能有一个机械驱动器(而不是SSD) - 需要一段时间才能找到数据。我怀疑你可以轻松地进行优化,而无需缓存结果并在将来的查询中使用缓存。 – Mjh

回答

0

计划A:使用公共数据创建临时表。

计划B:使用@variables。例如:

SELECT @A := expression1...; 
SELECT @B := expression2...; 
SELECT ... @A ... @B ... @A ...