2015-09-16 140 views
0

我已经注意到使用COALESCE(在我的情况下)来避免可能的NULL值在准备好的语句中会导致DB查询时间执行的性能下降。有人能解释我的根本原因是什么,我该如何克服这个问题?下面的查询样品:DB2 COALESCE - 对查询时间执行的显着影响

QUERY 1(执行时间3秒):

SELECT TABLE_A.Y, TABLE_B.X 
FROM ... 
WHERE Z = ? AND TABLE_A.ABC = ? AND 
    TABLE_A.QWERTY = ? AND TABLE_A.Q = TABLE_B.Q; 

QUERY 2(执行时间210秒):

SELECT TABLE_A.Y, TABLE_B.X 
FROM ... 
WHERE Z = ? AND (
    (COALESCE(?,'')='') OR 
    (TABLE_A.ABC = ? AND TABLE_A.QWERTY = ? AND TABLE_A.Q = TABLE_B.Q) 
); 

唯一的区别是使用( COALESCE(?, '')= '')。

+0

您的查询缺少'FROM'条款。但是您的问题的答案是“是”:更改'WHERE'子句可以并确实影响查询优化的方式。 –

+1

我会冒险猜测,主要原因是添加'OR'而不是'COALESCE()'。查询优化器无法知道'COALESCE(?,'')='')'的选择性。在比较查询计划后,你的“为什么”的答案会很明显。 – mustaccio

+0

为两个查询添加解释输出,以便我们可以进行有根据的猜测。看来OR是麻烦的原因。 –

回答

0

我看到的更大的问题是,QUERY 13占位符,而QUERY 24占位符。

我想你要做的是你想让你的占位符可选。

一个简单的方法做,这是解决问题1如下

SELECT TABLE_A.Y, TABLE_B.X 
FROM TABLE_A 
INNER JOIN TABLE_B ON TABLE_A.Q = TABLE_B.Q; 
WHERE Z = ? 
    AND TABLE_A.ABC = COALESCE(?,TABLE_A.ABC) 
    AND TABLE_A.QWERTY = COALESCE(?,TABLE_A.QWERTY) 
+0

其实你的命题会很好if表TABLE_A中的列ABC在数据库中是强制性的,但它不是。使用你的方法,如果列ABC的占位符将被null取得,结果将不正确。将列与其自身进行比较,仅在结果中给出具有肯定(NOT NULL)值的记录,而应该返回所有记录(包括NULL值)。这就是为什么(COALESCE(?,'')='')正在使用中。 我只是想知道是否有一个解决方案,以一些不会导致性能问题的构造来取代它,同时维护Prepared Statement。 – R4Di

+0

重要的是要记住总是有一个未更改的列值。如果将函数应用于列,则不能使用索引==较慢。 – Stavr00