|
|
|
Join selectivity в Oracle - округление до 6 знаков?
|
|||
|---|---|---|---|
|
#18+
Есть две большие таблицы - r и g. В каждой несколько миллиардов записей, будем считать по 10. Возьмем запрос который джойнит их по некоторой колонке : Код: plsql 1. 2. 3. Смотрим план, и видим кардиналити результата - 1! Стал читать как считается селективность джойна. Откопал что при отсутствии гистограмм по колонкам ( а их нет ) считается она по формуле автор1/ max( NDK(a.id), NDK(b.id ) ) где NDK - количество различных ключей. В данном случае, NDK для первой - миллионов по 300 ( для второй, скажем, миллион). Стало быть JSEL должна быть 1 разделить на 300 миллионов. И кардиналити должна получиться в районе 10 млрд / 300 млн = 35. Никак не один. Снимаем трассировку 10053, видим в ней следующее: Join Card: 0.000000 = outer (737084044.000000) * inner (389613700.000000) * sel (0.000000) Join Card - Rounded: 1 Computed: 0.00 Т.е. селективность он посчитал как 0.000000. Ну, если там округление до 6 знаков, то она конечно 0 и получится т.к. 1/300 миллионов с таким округлением даст 0. Но мне как-то тяжело представить чтобы оракл так облажался и действительно оставил лишь 6 знаков. Кому-нибудь что-нибудь известно по этому поводу? Также интересно, какие есть опции чтобы научить оракл корректно оценивать эстимейт таких джойнов. Реально там сотни тысяч и миллионы получаются строк в результате джойна. Посмотрю завтра что там помогут гистограммы, что у него получится, но честно говоря не хотелось бы, таблички очень большие и считать по ним гистограммы может оказаться очень затратно. ... |
|||
|
:
Нравится:
Не нравится:
|
|||
| 10.10.2017, 19:12 |
|
||
|
Join selectivity в Oracle - округление до 6 знаков?
|
|||
|---|---|---|---|
|
#18+
Valergrad, было и больше 100млрд, но такого случая никогда не встречал. Что-то у вас не так. Пришлите экспорт метадата и статистики этих таблиц с индексами. Ну и версию скажите. ... |
|||
|
:
Нравится:
Не нравится:
|
|||
| 10.10.2017, 19:28 |
|
||
|
Join selectivity в Oracle - округление до 6 знаков?
|
|||
|---|---|---|---|
|
#18+
12.2 тестовые таблички Код: plsql 1. 2. 3. 4. 5. 6. 7. 8. 9. 10. 11. 12. 13. 14. 15. 16. 17. 18. 19. 20. 21. 22. 23. 24. 25. 26. 27. 28. 29. 30. 31. 32. 33. 34. 35. 36. 37. 38. 39. 40. 41. 42. 43. 44. 45. 46. 47. 48. 49. 50. 51. 52. 53. 54. 55. 56. 57. 58. 59. 10053: JOIN CARD Код: plsql 1. 2. ... |
|||
|
:
Нравится:
Не нравится:
|
|||
| 10.10.2017, 20:37 |
|
||
|
Join selectivity в Oracle - округление до 6 знаков?
|
|||
|---|---|---|---|
|
#18+
xtender, мы пока еще по старинке, на 11.2.0.4. Как буду дома запущу ваш тест. ... |
|||
|
:
Нравится:
Не нравится:
|
|||
| 10.10.2017, 21:02 |
|
||
|
Join selectivity в Oracle - округление до 6 знаков?
|
|||
|---|---|---|---|
|
#18+
xtender, действительно, ваш тест на 11.2.0.4 показывает что никакого округления нет. К сожалению, выложить DDL таблицы так просто не могу - там мегабайт текста ( т.к. тысячи партиций и индексы и т.п. ). Пока я делаю простейший воспроизводимый кейс, могу я задать такой вопрос? Возможно ли, что дело в том, что на таблице интервалы LOW_VALUE и HIGH_VALUE на таблице не пересекаются на поле которое джойнится? Я почитал цикл статей: https://www.toadworld.com/platforms/oracle/w/wiki/11527.join-cardinality-estimation-methods-part-1 и здесь пишут, что для многих случаев есть такая проверка на интервалы ( пусть ее и нет в этой статье на простейший случай который у нас - где нет гистограмм ). Правда я попробовал: взял и вручную поставил пересекающиеся интервалы в dba_tab_columns ( через export_statistics -> update columns с6 и r1 -> import_statistics ) и флашнул пул. Но, не помогло - кардиналити по прежнему 1. Возможно, зависит еще от чего-то, что я не отредактировал. Если бы где-то найти точно, от чего зависит джойн селективность, то я бы поправил ее на правильную и проблема стала бы понятна. Вариант: "собрать правильную статистику в которой все учтено" к сожалению прямо сейчас не подходит, т.к. собираться статистика на одной из этих таблиц будет несколько дней. ... |
|||
|
:
Нравится:
Не нравится:
|
|||
| 11.10.2017, 18:45 |
|
||
|
Join selectivity в Oracle - округление до 6 знаков?
|
|||
|---|---|---|---|
|
#18+
Valergrad, Легко проверить моим же тестом на вашей базе: измените значения в create table - это и будут ваши low/high values ... |
|||
|
:
Нравится:
Не нравится:
|
|||
| 11.10.2017, 19:29 |
|
||
|
Join selectivity в Oracle - округление до 6 знаков?
|
|||
|---|---|---|---|
|
#18+
Да, проверка дает кардиналити 1. Т.е. low/high_value действительно участвует в расчете селективности. Вопрос: почему же у меня она 1, несмотря на то, что интервалы теперь уже, пересекаются? Что еще участвует в расчете join selectivity? Вы нигде не натыкались на действительно полное описание этой формулы? ... |
|||
|
:
Нравится:
Не нравится:
|
|||
| 11.10.2017, 20:19 |
|
||
|
Join selectivity в Oracle - округление до 6 знаков?
|
|||
|---|---|---|---|
|
#18+
Наконец простой скрипт в котором воспроизводится это поведение. Скрипт создает таблицу, заполняет статистику, импортирует ее, наконец сам запрос и план: Скрипт Код: plsql 1. 2. 3. 4. 5. 6. 7. 8. 9. 10. 11. 12. 13. 14. 15. 16. 17. 18. 19. 20. 21. 22. 23. 24. 25. 26. 27. 28. 29. 30. 31. 32. 33. 34. 35. 36. 37. 38. 39. 40. 41. 42. 43. 44. 45. 46. 47. 48. 49. 50. 51. 52. 53. 54. 55. 56. 57. 58. 59. 60. 61. 62. 63. 64. 65. 66. 67. 68. 69. 70. 71. 72. 73. 74. 75. 76. 77. 78. 79. 80. 81. 82. 83. 84. 85. 86. 87. 88. 89. 90. 91. 92. 93. 94. 95. 96. 97. 98. 99. 100. 101. 102. 103. 104. 105. 106. 107. 108. 109. 110. 111. 112. 113. 114. 115. 116. 117. 118. 119. 120. 121. 122. 123. 124. 125. 126. 127. 128. 129. 130. 131. 132. 133. 134. 135. 136. 137. 138. 139. 140. 141. 142. 143. 144. 145. 146. 147. 148. 149. 150. 151. 152. 153. 154. 155. 156. 157. 158. 159. 160. 161. 162. 163. 164. 165. 166. 167. 168. 169. 170. 171. 172. 173. 174. 175. 176. 177. 178. 179. 180. 181. 182. 183. 184. 185. 186. 187. 188. 189. 190. 191. 192. 193. 194. 195. 196. 197. 198. 199. 200. 201. 202. 203. 204. 205. 206. 207. 208. 209. 210. 211. 212. 213. 214. 215. 216. 217. 218. 219. 220. 221. 222. 223. 224. 225. 226. 227. 228. 229. 230. 231. 232. 233. 234. 235. 236. 237. 238. 239. 240. 241. 242. 243. 244. 245. 246. 247. 248. 249. 250. 251. 252. 253. 254. 255. 256. 257. 258. 259. 260. 261. 262. 263. 264. 265. 266. 267. 268. 269. 270. 271. 272. 273. 274. 275. 276. 277. 278. 279. 280. 281. 282. 283. 284. 285. 286. 287. 288. 289. 290. 291. 292. 293. 294. 295. 296. 297. Версия напомню 11.2.0.4 Посмотрите плиз, у вас то же самое или нет. Трассировку 10053 сейчас снять не могу, админ ушел домой :) ... |
|||
|
:
Нравится:
Не нравится:
|
|||
| 11.10.2017, 22:22 |
|
||
|
Join selectivity в Oracle - округление до 6 знаков?
|
|||
|---|---|---|---|
|
#18+
Да, оказывается границы я не везде поправил ( с ручными правками оно так). После более корректной поправки границ кардиналити стало аккуратным. корректная статистикаSRC PLSQL]CREATE TABLE RR15 ( PART_ID INTEGER NOT NULL, KEY_ID INTEGER NOT NULL ) NOCOMPRESS RESULT_CACHE (MODE DEFAULT) PARTITION BY RANGE (PART_ID) ( PARTITION P_RUN_0 VALUES LESS THAN (1) NOCOMPRESS, PARTITION P_RUN_9229 VALUES LESS THAN (9230) NOCOMPRESS ) PARALLEL ( DEGREE 8 INSTANCES 1 ); CREATE TABLE GG15 ( PART_ID INTEGER, KEY_ID INTEGER ) NOCOMPRESS RESULT_CACHE (MODE DEFAULT) PARTITION BY RANGE (PART_ID) ( PARTITION P_RUN_0 VALUES LESS THAN (1) NOCOMPRESS, PARTITION P_RUN_9229 VALUES LESS THAN (9230) NOCOMPRESS ); --- create statistics table CREATE TABLE STATTAB ( STATID VARCHAR2(30 BYTE), TYPE CHAR(1 BYTE), VERSION NUMBER, FLAGS NUMBER, C1 VARCHAR2(30 BYTE), C2 VARCHAR2(30 BYTE), C3 VARCHAR2(30 BYTE), C4 VARCHAR2(30 BYTE), C5 VARCHAR2(30 BYTE), N1 NUMBER, N2 NUMBER, N3 NUMBER, N4 NUMBER, N5 NUMBER, N6 NUMBER, N7 NUMBER, N8 NUMBER, N9 NUMBER, N10 NUMBER, N11 NUMBER, N12 NUMBER, D1 DATE, R1 RAW(32), R2 RAW(32), CH1 VARCHAR2(1000 BYTE), CL1 CLOB ) LOB (CL1) STORE AS ( ENABLE STORAGE IN ROW CHUNK 16384 RETENTION STORAGE ( INITIAL 80K NEXT 1M MINEXTENTS 1 MAXEXTENTS UNLIMITED PCTINCREASE 0 BUFFER_POOL DEFAULT )) RESULT_CACHE (MODE DEFAULT) NOCOMPRESS ; CREATE INDEX STATTAB ON STATTAB (STATID, TYPE, C5, C1, C2, C3, C4, VERSION); -- adding statistics Insert into STATTAB(STATID, TYPE, VERSION, FLAGS, C1, C2, C4, C5, N1, N2, N3, N5, N8, D1) Values ('GG15', 'C', 6, 2, 'GG15', 'P_RUN_0', 'KEY_ID', user, 0, 0, 0, 0, 0, TO_DATE('07/29/2015 17:36:21', 'MM/DD/YYYY HH24:MI:SS')); Insert into STATTAB (STATID, TYPE, VERSION, FLAGS, C1, C2, C4, C5, N1, N2, N3, N5, N8, D1) Values ('GG15', 'C', 6, 2, 'GG15', 'P_RUN_0', 'PART_ID', user, 0, 0, 0, 0, 0, TO_DATE('07/29/2015 17:36:21', 'MM/DD/YYYY HH24:MI:SS')); Insert into STATTAB (STATID, TYPE, VERSION, FLAGS, C1, C2, C5, N1, N2, N3, N4, N9, D1) Values ('GG15', 'T', 6, 2, 'GG15', 'P_RUN_0', user, 0, 0, 0, 2000, 0, TO_DATE('07/29/2015 17:36:21', 'MM/DD/YYYY HH24:MI:SS')); Insert into STATTAB (STATID, TYPE, VERSION, FLAGS, C1, C2, C4, C5, N1, N2, N3, N4, N5, N6, N7, N8, D1, R1, R2) Values ('GG15', 'C', 6, 2, 'GG15', 'P_RUN_9229', 'KEY_ID', user, 1318, 0.000758725341426404, 1311, 6913, 0, 1, 11027179228, 8, TO_DATE('10/03/2017 08:57:11', 'MM/DD/YYYY HH24:MI:SS'), 'C6020B1A5D5962', 'C6020B1A5F1D19'); Insert into STATTAB (STATID, TYPE, VERSION, FLAGS, C1, C2, C4, C5, N1, N2, N3, N4, N5, N6, N7, N8, D1, R1, R2) Values ('GG15', 'C', 6, 2, 'GG15', 'P_RUN_9229', 'PART_ID', user, 1, 1, 1, 6913, 0, 9229, 9229, 4, TO_DATE('10/03/2017 08:57:11', 'MM/DD/YYYY HH24:MI:SS'), 'C25D1E', 'C25D1E'); Insert into STATTAB (STATID, TYPE, VERSION, FLAGS, C1, C2, C5, N1, N2, N3, N4, N9, D1) Values ('GG15', 'T', 6, 2, 'GG15', 'P_RUN_9229', user, 691300000, 4546, 80, 6913, 0, TO_DATE('10/03/2017 08:57:10', 'MM/DD/YYYY HH24:MI:SS')); Insert into STATTAB (STATID, TYPE, VERSION, FLAGS, C1, C4, C5, N1, N2, N3, N4, N5, N6, N7, N8, D1, R1, R2) Values ('GG15', 'C', 6, 2, 'GG15', 'KEY_ID', user, 752143, 0.00000132953441034484, 752143, 53322510, 9609, 217162, 2226708711, 6, TO_DATE('10/02/2015 14:15:09', 'MM/DD/YYYY HH24:MI:SS'), 'C316483F', 'C5171B47580C'); Insert into STATTAB (STATID, TYPE, VERSION, FLAGS, C1, C4, C5, N1, N2, N3, N4, N5, N6, N7, N8, D1, R1, R2) Values ('GG15', 'C', 6, 2, 'GG15', 'PART_ID', user, 72, 0.0138888888888889, 72, 53332119, 0, 1, 10000, 3, TO_DATE('10/02/2015 14:15:09', 'MM/DD/YYYY HH24:MI:SS'), 'C102', 'C25D2D'); Insert into STATTAB (STATID, TYPE, VERSION, FLAGS, C1, C5, N1, N2, N3, N4, N9, D1) Values ('GG15', 'T', 6, 2, 'GG15', user, 3000000000, 301828, 74, 3000000000, 0, TO_DATE('10/02/2015 14:15:09', 'MM/DD/YYYY HH24:MI:SS')); Insert into STATTAB (STATID, TYPE, VERSION, FLAGS, C1, C2, C4, C5, N1, N2, N3, N5, N8, D1) Values ('RR15', 'C', 6, 2, 'RR15', 'P_RUN_0', 'KEY_ID', user, 0, 0, 0, 0, 0, TO_DATE('07/29/2015 17:36:57', 'MM/DD/YYYY HH24:MI:SS')); Insert into STATTAB (STATID, TYPE, VERSION, FLAGS, C1, C2, C4, C5, N1, N2, N3, N5, N8, D1) Values ('RR15', 'C', 6, 2, 'RR15', 'P_RUN_0', 'PART_ID', user, 0, 0, 0, 0, 0, TO_DATE('07/29/2015 17:36:57', 'MM/DD/YYYY HH24:MI:SS')); Insert into STATTAB (STATID, TYPE, VERSION, FLAGS, C1, C2, C5, N1, N2, N3, N4, N9, D1) Values ('RR15', 'T', 6, 2, 'RR15', 'P_RUN_0', user, 0, 0, 0, 2000, 0, TO_DATE('07/29/2015 17:36:57', 'MM/DD/YYYY HH24:MI:SS')); Insert into STATTAB (STATID, TYPE, VERSION, FLAGS, C1, C2, C4, C5, N1, N2, N3, N4, N5, N6, N7, N8, D1, R1, R2) Values ('RR15', 'C', 6, 2, 'RR15', 'P_RUN_9229', 'KEY_ID', user, 1194740, 0.000000837002192945746, 1147884, 3849929, 0, 1, 11027179228, 8, TO_DATE('10/03/2017 09:45:10', 'MM/DD/YYYY HH24:MI:SS'), 'C6020B1A485A3D', 'C6020B1C125D1D'); Insert into STATTAB (STATID, TYPE, VERSION, FLAGS, C1, C2, C4, C5, N1, N2, N3, N4, N5, N6, N7, N8, D1, R1, R2) Values ('RR15', 'C', 6, 2, 'RR15', 'P_RUN_9229', 'PART_ID', user, 1, 1, 1, 3849929, 0, 9229, 9229, 4, TO_DATE('10/03/2017 09:45:10', 'MM/DD/YYYY HH24:MI:SS'), 'C25D1E', 'C25D1E'); Insert into STATTAB (STATID, TYPE, VERSION, FLAGS, C1, C2, C5, N1, N2, N3, N4, N9, D1) Values ('RR15', 'T', 6, 2, 'RR15', 'P_RUN_9229', user, 384992900, 741068, 38, 3849929, 0, TO_DATE('10/03/2017 09:45:10', 'MM/DD/YYYY HH24:MI:SS')); Insert into STATTAB (STATID, TYPE, VERSION, FLAGS, C1, C4, C5, N1, N2, N3, N4, N5, N6, N7, N8, D1, R1, R2) Values ('RR15', 'C', 6, 2, 'RR15', 'KEY_ID', user, 124175360, 0.00000000805312744815074, 124175360, 24471738541, 0, 1678717512, 2226708711, 7, TO_DATE('08/04/2016 18:14:07', 'MM/DD/YYYY HH24:MI:SS'), 'C316483F', 'C5171B47580C'); Insert into STATTAB (STATID, TYPE, VERSION, FLAGS, C1, C4, C5, N1, N2, N3, N4, N5, N6, N7, N8, D1, R1, R2) Values ('RR15', 'C', 6, 2, 'RR15', 'PART_ID', user, 303, 0.0033003300330033, 303, 24471738541, 0, 1, 10000, 4, TO_DATE('08/04/2016 18:14:07', 'MM/DD/YYYY HH24:MI:SS'), 'C102', 'C25D2D'); Insert into STATTAB (STATID, TYPE, VERSION, FLAGS, C1, C5, N1, N2, N3, N4, N9, D1) Values ('RR15', 'T', 6, 2, 'RR15', user, 24471738541, 45952471, 38, 24471738541, 0, TO_DATE('08/04/2016 18:14:07', 'MM/DD/YYYY HH24:MI:SS')); COMMIT; exec dbms_stats.import_table_stats ( ownname => user , stattab => 'STATTAB', tabname => 'RR15', statid => 'RR15') ; exec dbms_stats.import_table_stats ( ownname => user , stattab => 'STATTAB', tabname => 'GG15', statid => 'GG15') ; SELECT /*+ noparallel */ * FROM GG15 g, RR15 r WHERE 1 = 1 and r.part_id = 9229 --and g.part_id = 9229 and g.key_id = r.key_id;[/SRC] Итого получается что джойн селективность зависит от двух вещей - границы интервалов и NDK. Теперь буду думать как нам пофиксить это поудобней не считая. ... |
|||
|
:
Нравится:
Не нравится:
|
|||
| 11.10.2017, 23:14 |
|
||
|
Join selectivity в Oracle - округление до 6 знаков?
|
|||
|---|---|---|---|
|
#18+
Valergrad, https://github.com/xtender/xt_scripts/blob/master/stats/set_high_and_low_value_of_number_cols.sql ... |
|||
|
:
Нравится:
Не нравится:
|
|||
| 12.10.2017, 00:10 |
|
||
|
Join selectivity в Oracle - округление до 6 знаков?
|
|||
|---|---|---|---|
|
#18+
там же рядом и для дат валяется: https://github.com/xtender/xt_scripts/tree/master/stats ... |
|||
|
:
Нравится:
Не нравится:
|
|||
| 12.10.2017, 00:11 |
|
||
|
|

start [/forum/topic.php?fid=52&msg=39535097&tid=1885121]: |
0ms |
get settings: |
10ms |
get forum list: |
14ms |
check forum access: |
4ms |
check topic access: |
4ms |
track hit: |
197ms |
get topic data: |
10ms |
get forum data: |
2ms |
get page messages: |
61ms |
get tp. blocked users: |
2ms |
| others: | 241ms |
| total: | 545ms |

| 0 / 0 |
