|
QueryPlan: GetRangeWithMismatchedTypes
|
|||
---|---|---|---|
#18+
Господа, вроде не пятница, а что то лыжи не едут. имеем на входе: Код: sql 1. 2. 3.
DSOPERDAY это пользовательский тип вида Код: sql 1. 2. 3. 4. 5.
в табличке tOperPart колонка OperDate типа DSOPERDAY. сиквел об этом прекрасно уведомлен, поэтому строя план для первого стейтмента в батче он применяет специальную оптимизацию что бы выстроить диапазон сканирования исходя из типа колонки оба запроса возвращают одинаковые результаты в три строки что в принципе и должно быть. анализируя структуру плана у меня рвет шаблон поскольку я вижу что поведение должно бы было быть другим по сути. план для всего батча Код: xml 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.
я не очень понимаю как так получается, судя по плану для первого запроса оптимизатор использует функцию получения диапазона с приведения типов для задания диапазона сканирования. но что примечательно дальше по плану для сканирования индекса он задает диапазон вида: Код: sql 1. 2. 3. 4. 5. 6. 7. 8. 9. 10. 11. 12. 13. 14. 15. 16. 17. 18. 19. 20. 21. 22. 23.
для вычисления внутренней функции GetRangeWithMismatchedTypes(NULL,[@d1],(42)) получается у нас данная конструкция была бы эквивалентом псеводкод Код: sql 1. 2.
но это не так потому что предикат у нас меньше-равно в запросе. может ли получаться так что внутренняя функция меняет значение для Expr1005 и оно становится не 20160616 а 20160617? иначе я не понимаю как в плане присутствуют диапазоны с типом ScanType = GT/LT а результаты запросов совпадают? ... |
|||
:
Нравится:
Не нравится:
|
|||
17.06.2021, 21:19 |
|
QueryPlan: GetRangeWithMismatchedTypes
|
|||
---|---|---|---|
#18+
add: кстати для запроса с литералом он выстраивает план с типом сканирования диапазона правильного типа: Код: sql 1.
Код: xml 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.
и тут у меня вопросов к нему нет, а вот при использовании GetRangeWithMismatchedTypes чето "нито" ... |
|||
:
Нравится:
Не нравится:
|
|||
17.06.2021, 21:54 |
|
QueryPlan: GetRangeWithMismatchedTypes
|
|||
---|---|---|---|
#18+
felix_ff, Честно говоря, особо не вникал. У GetRangeWithMismatchedTypes третий параметр - набор флагов. Описан тут - https://sqlserverfast.com/epr/index-seek/#DynSeekRange В вашем случае значение флагов 42 (двоичное 101010), т.е. биты 2 и 4 установлены. ... |
|||
:
Нравится:
Не нравится:
|
|||
18.06.2021, 10:59 |
|
QueryPlan: GetRangeWithMismatchedTypes
|
|||
---|---|---|---|
#18+
felix_ff, по идее, не должно влиять на план, но если попробовать where OperDate <= CAST(@d2 AS DATETIME)? ... |
|||
:
Нравится:
Не нравится:
|
|||
18.06.2021, 11:06 |
|
QueryPlan: GetRangeWithMismatchedTypes
|
|||
---|---|---|---|
#18+
Владислав Колосов, оно на план по сути дела не влияет и вот это меня больше всего смущает. если дословно интерпретировать план получается что написанно взять такие то строки где колонка даты в интервале (~; '20210616') хотя если смотреть условие самой квери то там по сути условие (~; '20210616'], и работает то главное именно так как нужно, но почему он в ScanType ставит LT вместо LE мне непонятно. invm, да посмотрел флаги немного странно написано, если считать по статье на 42 выставлены 2,4,6 биты тут чето мутно написано, он их местами что ли меняет в зависимоти от флагов? GetRangeWithMismatchedTypes(NULL,[@d1],(42)) у нас должно получаться условие [dbo].[tOperPart] where [OperDate] > Expr1 and [OperDate] < Expr2 если мы считаем что выставлены биты 2,4,6 Bit-2 (4): When this bit is on, the value in Expr1 represents the end of the interval. When this bit is off, the interval has no end. The latter is e.g. the case for an interval defined by just a single > or >= comparison. Bit-4 (16): Only used when bit-2 is on. When this bit is on, the value in Expr1 is included in the interval. When it is off, the value in Expr1 is not included. Bit-6 (64) and bit-7 (128): Appear to be unused. получается что кондишн будет таким: [dbo].[tOperPart] where [OperDate] >= NULL and [OperDate] < @date что не особо сходится с запросом нумерация может быть с нуля тогда возможно выставлены 1,3,5 что больше походит на правду 42 (2 + 8 + 32) Bit-1 (2) : Represents the ANSI_NULLS setting for equality comparisons with NULL. This bit is set to 0 when ANSI_NULLS is off, but also when an IS NULL condition is internally converted to an equality comparison for a dynamic seek range. Bit-3 (8) : When this bit is on, the value in Expr2 represents the start of the interval. When this bit is off, the interval has no start. The latter is e.g. the case for an interval defined by just a single < or <= comparison. Bit-5 (32) : Only used when bit-3 is on. When this bit is on, the value in Expr2 is included in the interval. When it is off, the value in Expr2 is not included. тогда конечный кондишн будет таким: [dbo].[tOperPart] where [OperDate] > NULL and [OperDate] <= @date если читать по последней фразе, но я не понимаю как интерпретировать "When this bit is on, the value in Expr2 represents the start of the interval." это равносильно [dbo].[tOperPart] where [OperDate] >= Expr2 (@date) and [OperDate] < Expr1 (null)? или это равносильно StartInterval в QueryPlan? Код: xml 1. 2. 3. 4. 5. 6. 7. 8. 9. 10. 11. 12.
но опять тогда какая то джигурда выходит. вообщем по описанию я не очень понимаю как выйти на ситуацию когда Expr2 будет @date и в каком месте в плане он будет показан так что бы выполнялось условие что скан строк идет до даты параметра @date включительно ... |
|||
:
Нравится:
Не нравится:
|
|||
18.06.2021, 13:53 |
|
QueryPlan: GetRangeWithMismatchedTypes
|
|||
---|---|---|---|
#18+
felix_ff, Можно попробовать посмотреть какие значения в Expr... https://www.sqlshack.com/query-trace-column-values/ ... |
|||
:
Нравится:
Не нравится:
|
|||
18.06.2021, 14:20 |
|
QueryPlan: GetRangeWithMismatchedTypes
|
|||
---|---|---|---|
#18+
invm, да, спасибо убедился. у него получается что expr1040 - null; expr1041 - '20210616', expr1039 - флаги в 42 соответствует тому что он рисует в плане: Код: xml 1. 2. 3. 4. 5. 6. 7. 8. 9. 10. 11. 12. 13. 14. 15. 16. 17. 18. 19. 20. 21. 22.
но в плане так же в SeekPredicate попрежнему Код: xml 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.
ну и при этом Код: xml 1.
хотя строк для [operDate] < '20210616' рельно нет. все в дате '20210616' по-видимому где то внутри все таки используется значение колонки expr1039, но в плане его реально не видно. ... |
|||
:
Нравится:
Не нравится:
|
|||
18.06.2021, 14:58 |
|
QueryPlan: GetRangeWithMismatchedTypes
|
|||
---|---|---|---|
#18+
напомните мне такую вещь, я все это действо с разбором полетов затеял потому что изначально разбирал несколько иной случай, но в итоге вылез на эту особенность в плане. у нас физ.оператор соединения NL прекратит обработку левого входа если в правом ничего не найдет? допустим у нас левый вход заведомо вернет 3 строки, в правом заведомо ничего не вернется, обязан ли левый вход быть выбран полностью? ... |
|||
:
Нравится:
Не нравится:
|
|||
18.06.2021, 15:04 |
|
QueryPlan: GetRangeWithMismatchedTypes
|
|||
---|---|---|---|
#18+
felix_ff допустим у нас левый вход заведомо вернет 3 строки, в правом заведомо ничего не вернется, обязан ли левый вход быть выбран полностью? Код: sql 1. 2. 3. 4. 5. 6. 7. 8. 9. 10. 11. 12. 13. 14. 15. 16. 17. 18. 19. 20. 21. 22. 23.
В этом примере даже к таблицам нет обращений. Все задавлено уже при компиляции. ... |
|||
:
Нравится:
Не нравится:
|
|||
18.06.2021, 15:47 |
|
QueryPlan: GetRangeWithMismatchedTypes
|
|||
---|---|---|---|
#18+
invm, ну да, я это тоже заметил. у меня просто был несколько специфичный пример который я за уши притянул в ходе тестов. приведу его для наглядности Код: sql 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.
тут интересное как раз поведение вырисовывается если форсировать порядок соединений. он начинает сканирование индекса на #o, но после того как берет первую строку видит что правый вход нихрена не дал и дальше уже не сканирует. это мне немного глаза приоткрыло :) но в целом ситуация понятна. с основной своей проблемой я разобрался там хреновая логика была, но вот вопросы к интервалам сканирования в планах пока остались. ... |
|||
:
Нравится:
Не нравится:
|
|||
18.06.2021, 16:15 |
|
QueryPlan: GetRangeWithMismatchedTypes
|
|||
---|---|---|---|
#18+
felix_ff он начинает сканирование индекса на #o, но после того как берет первую строку видит что правый вход нихрена не дал и дальше уже не сканирует. Там же на правом входе инвариантный подзапрос. Если он ничего не вернул, то нет смысла далее крутить NL. ... |
|||
:
Нравится:
Не нравится:
|
|||
18.06.2021, 16:59 |
|
|
start [/forum/topic.php?fid=46&fpage=21&tid=1684584]: |
0ms |
get settings: |
11ms |
get forum list: |
14ms |
check forum access: |
4ms |
check topic access: |
4ms |
track hit: |
55ms |
get topic data: |
13ms |
get forum data: |
3ms |
get page messages: |
51ms |
get tp. blocked users: |
2ms |
others: | 18ms |
total: | 175ms |
0 / 0 |