![]() | |
![]() |
| | Thread Tools | Display Modes |
#1
| |||
| |||
|
#2
| |||
| |||
|
|
In DB2 9.5.8 on AIX, I have come across a bad query plan that is to some extent caused by the optimizer wrongly estimating the initial NLJOIN (nested-loop join) of the plan (with a more accurate estimate, it would not have chosen that plan). Here is the gist of the situation: we have a join of two tables over two columns, where the column statistics and the combined column statistics in both tables are known to the optimizer. |
#3
| |||
| |||
|
|
Oliver Schoett wrote: In DB2 9.5.8 on AIX, I have come across a bad query plan that is to some extent caused by the optimizer wrongly estimating the initial NLJOIN (nested-loop join) of the plan (with a more accurate estimate, it would not have chosen that plan). Here is the gist of the situation: we have a join of two tables over two columns, where the column statistics and the combined column statistics in both tables are known to the optimizer. The problem observed is that the optimizer ignores the joint column statistics and instead multiplies the selectivities of the fields involved. *When the fields are correlated, their combined selectivity is much weaker than this product. An explanation for this phenomenon can be found in the following article by an IBM engineer: * * Understand column group statistics in DB2 http://www.ibm.com/developerworks/da...cle/dm-0612kap... The article explains that a joint column statistic is used only if the following conditions are true: (1) All the fields must occur in equations between one table A and one table B, (2) One of the two tables must be the "parent table" of the join in the sense that (3) for each join condition, the column statistics of the fields involved (COLCARD, LOW2KEY, HIGH2KEY) must be consistent with the child column values being a subset of the parent column values. In this case, the joint column statistics on the parent table are used. The problem in our case was that the COLCARD values were greater in one table for one field and in the other table for the other field, so that no parent-child relation betwen the tables existed. Our query performed 650 times faster after we established a parent-child relationship by modifying the column statistics in the SYSSTAT schema. However, this has the side effect that the modified statistics are no longer accurate. Our customer is skeptical about this approach and wonders whether there is a cleaner way of making the optimizer consider the joint column statistics? Regards, Oliver Schoett |
#4
| |||
| |||
|
|
I think what you are looking for instead of manually updating the statistics is using a statistical view: http://www.ibm.com/developerworks/da...e/dm-0612chen/ |
#5
| |||
| |||
|
|
Here is the gist of the situation: we have a join of two tables over two columns, where the column statistics and the combined column statistics in both tables are known to the optimizer. The query is as follows: select * from M, P where M.R1 = P.F1 and M.R2 = P.F2 The table M has an index (R2, R1, ...), table P has an index (F1, F2, ...). Both indexes have FIRST2KEYCARD values in syscat.indexes. The cardinalities are as follows M.R1 P.F1 126* 100 FIRST2KEYCARD FIRST2KEYCARD 182981 4300 M.R2 P.F2 3107 3128* From the cardinalities of the base tables and the optimizer's estimate of the result cardinality, it can be seen that the optimizer calculates the selectivity of the join predicates to be 1 / 394128 = 1 / (126 * 3128) |
#6
| |||
| |||
|
|
On 2011-11-22 16:28, Oliver Schoett wrote: [...] Here is the gist of the situation: we have a join of two tables over two columns, where the column statistics and the combined column statistics in both tables are known to the optimizer. The query is as follows: select * from M, P where M.R1 = P.F1 and M.R2 = P.F2 The table M has an index (R2, R1, ...), table P has an index (F1, F2, ...). Both indexes have FIRST2KEYCARD values in syscat.indexes. The cardinalities are as follows M.R1 P.F1 126* 100 FIRST2KEYCARD FIRST2KEYCARD 182981 4300 M.R2 P.F2 3107 3128* From the cardinalities of the base tables and the optimizer's estimate of the result cardinality, it can be seen that the optimizer calculates the selectivity of the join predicates to be 1 / 394128 = 1 / (126 * 3128) From my understanding (which is a bit limited), the selectivity estimate for a join is 1 / max(cc1, cc2), AND corresponds to * which would give us: 1 / max(126, 100) * 1 / max(3107, 3128) I don't have the time right now, but I'll try to investigate whether I can get db2 to use FIRST2KEYCARD as an estimate for join selectivity and get back on this. |
#7
| ||||
| ||||
|
|
From my understanding (which is a bit limited), the selectivity estimate for a join is 1 / max(cc1, cc2), AND corresponds to * which would give us: 1 / max(126, 100) * 1 / max(3107, 3128) |
|
| 4880,92 9,93351 |
|
| 4880,92 9,93351 |
|
| 2,37706e+007 3,83622e+006 |
#8
| |||
| |||
|
|
Lennart Jonsson wrote: From my understanding (which is a bit limited), the selectivity estimate for a join is 1 / max(cc1, cc2), AND corresponds to * which would give us: 1 / max(126, 100) * 1 / max(3107, 3128) Yes, this is exactly what the optimizer seems to be doing, ignoring the FIRST2KEYCARDS of 182981 and 4300 and thus arriving at a cardinality estimate that is far too low. In my mind, it should use the highest possible estimate, which is 1 / min(FIRST2KEYCARD(M.R1, M.R2), FIRST2KEYCARD(P.F1, P.F2) = 1 / min(182981, 4300) = 1 / 4300 That comes much closer to the actual value. |
|
I now have access to version 9.7.5 of DB2 and can present the actual cardinalities of the join, obtained with Serge Rielau's package (https://www.ibm.com/developerworks/m...ts23?lang=en): |
![]() |
| Thread Tools | |
| Display Modes | |
| |