现代以代价为基础的查询优化器使用备忘录结构为一个有效的查询运行计划组织搜索空间。例如,考虑一个oid连接路径‘A.B.C.D’.我们可以在这条路径任何点启动计算。它的备忘录结构可以用一个(大)MAL程序来表示。备忘录的水平用choice运算封装。第二个参数指示哪些指令去被考虑代价计算。
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 | |
scheduler.choice()操作为每个目标变量调用内置的getVolume且期待一个整数值代价。在这个事例里它返回总共参数使用的字节数。具有最低代价的目标变量被选择运行和剩余的变量被变成临时NOOP操作(你可能想重用备忘录)。它们会被解析器遗漏,同时在接下的调用中被调度器忽略。它减少了替换当我们在计划中处理时。一个内置朴素的代价函数会被使用。使用者可以提供一个私有的代价函数被定义为目标和a :lng结果带有多态参数的模式。它的实现可以使用完全的上下文信息去做决定。如,它可以跟踪在接下的语句中对目标变量的潜在使用去决定总代价当这一步被考虑到最后的结果。
在达到下个选择点前,一个完整计划很可能包含其他表达式去准备或使用目标变量。choice运算的任务是避免不必要的操作。MAL块应该被调用者私有拥有,这样确保了scheduler.isolation()。模式的细化也组成部分计划代价分析。然后你不再需要包含一个固定的代价函数。
1 2 3 4 5 6 7 8 9 10 | |
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 | |
1.合并表优化:
一个合并相关表(MAT)描述符定义了一个可兼容BAT的有序的类型集合,它的并代表一个单一(虚)BAT。MAL可能代表一个分区的BAT(看BPM),也可以是一个在一个程序块中临时BATs的任意集合。MAL的定义存在于一个单代码块的范围。MAT优化简单地扩展计划去基于指令的基础上处理它的模块。只有当遇上一个blocking操作时,相关的BAT才会被实例化。当没有被实例化,MAL对象不能作为参数传入到任何函数。简单地说,因为MAL不被类型系统所知道和没有底层的操作意识到它的存在。
在MAL优化器的第一种方法中,我们假设在MAT序列中第一个BAT被使用累加器。进一步,没有语义知识被使用去减少可能无用的连接。然而,我们限制对一个简单参数的扩展。这在后阶段被改变当一个以代价为基础的计算被用于区分不同的。为了说明,考虑:
1 2 3 4 5 6 7 8 9 10 11 12 13 | |
选择和聚集操作可以使用MAT简单地重写:
1 2 3 4 5 6 7 8 9 10 11 12 | |
print操作还没有MAT语义。它需要一个在调用时不会产生头的函数。然而,在输出前,我们可以打包元素:
1 2 | |
对于连接,在不知道人和关于组件属性的情况下,我们必须生成所有可能的组合。当前的启发是限制扩展一个简单的参数。这导致:
1 2 3 4 | |
这模式的不足是在MAL语句中隐藏爆炸。优化器的挑战从对MAT元素的属性的监测中找出最小的。如,在处理前,它可能尝试去部分地打包元素。这是一个运行调度的决定。相反的,在更复杂的程序分析中毕竟系统可以使用MAT迭代器去避免打包.
1 2 3 4 5 6 7 8 9 | |
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 298 299 300 301 302 303 304 305 306 307 308 309 310 311 312 313 314 315 316 317 318 319 320 321 322 323 324 325 326 327 328 329 330 331 332 333 334 335 336 337 338 339 340 341 342 343 344 345 346 347 348 349 350 351 352 353 354 355 356 357 358 359 360 361 362 363 364 365 366 367 368 369 370 371 372 373 374 375 376 377 378 379 380 381 382 383 384 385 386 387 388 389 390 391 392 393 394 395 396 397 398 399 400 401 402 403 404 405 406 407 408 409 410 411 412 413 414 415 416 417 418 419 420 421 422 423 424 425 426 427 428 429 430 431 432 433 434 435 436 437 438 439 440 441 442 443 444 445 446 447 448 449 450 451 452 453 454 455 456 457 458 459 460 461 462 463 464 465 466 467 468 469 470 471 472 | |
2.多道编译优化:
MonetDB 操作多道概念是中轴的简单运用任何标量的函数的元素在一个容器里。任何操作CMD和它的多道转变【CMD】一起出现。给出CMD(T1,..,Tn)的标记:TR,它可以被使用同时【CMD】(bat[:any 1,:T1],…,bat[any 1,Tn]) :bat[any 1,Tr]。多道的语义在所有Bat值参数执行定位连接和对匹配的元组的每个组合执行CMD。所有的结果被收集在一个结果的BAT。所有但除一个参数外可能会被一个标量值替换。对多道操作通用的解决方案是把它们翻译成MAL循环。一个片段关于其行为:
1 2 3 4 | |
当前的实现需要目标类型要被清晰地被提到。由优化器产生的结果:
1 2 3 4 5 6 7 8 9 | |
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 | |
3.BAT分区优化
在老的PC地址空间受限和分布的存储的需要使BATs理想地被看重作为更小的BATs的并集,在给定有限的内存中处理。带有支持性的bat分区库bmp的PARTITION()优化器用可适配的数据库分段算法解决这问题。它被递增地设计带有一个中心是支持SQL front-end。特别是,被考虑的操作被限制为MAL的子集。一个在这集合外面的操作的出现终止优化器的活动。OPTIMIZER.PARTITIONS()操作寻找SQL列BAT的绑定和为了使用分区版本而准备代码。
我们使用两种是吸纳。第一种尝试寻找线性依赖数据的片段和在其构造一个迭代器。这种方法有些棘手,因为你必须对特殊的情况进行关照。特别是,在顺序构建操作的语义造成一些问题。navie()方法简单地看自个儿的操作和用迭代器围绕它们。一个别名的表被保留用来重用和探测已经分区的操作符。不足之处一个分区的BAT潜伏要读几次【这取决于变量可计算的重使用】和中间的读写。实验应该指明一个优化的一个。
4.窥孔优化
递归下降查询器很容易对产生更好的代码错失机会,因为有限的上下文被保留或向前看可用。窥孔优化器在这样递归的模式下建立和对优化器的‘错误’补救。窥孔模式的集合随着时间增长和front-end详细的变化应该可以预见。SQL frontend 严重依赖于一个中轴的生成oid序列的表。不幸的是,这是不能被看见和模式’$i := calc.oid(0@0); $j:= algebra.markT($k,$i);经常发生。这可以被’$j:= algebra.markT($k)’替换。另一个产生2-way指令序列例子是’$j:= algebra.markT($k); $l:= bat.reverse($j);’,这都可以用’$l:= algebra.markH($k);’替换。
reverse-reverse 操作也落入这个目录。相反的pairs 可能起因于front-end编译器的处理模式或者其它优化器步骤的副影响。这样的相反对应该越快去除越好,这样可以减小找到另外优化机会的复杂度。因所有的情况下我们应该保证被丢掉的中间结果不会被用于其他用途。
1 2 3 4 5 6 7 8 | |
这被窥孔优化器转化为:
1 2 3 | |
5.查询执行计划
一个普遍使用的数据结构去表示和操作一个查询是树(或图)。它的节点表示操作符和叶子表示操作数。这样的视图随手拈来当你要重组整块代码或者去建立一个从底到上建立优化计划,如使用备忘录结构。MAL优化器工具箱提供函数用树(图)结构覆盖任何的MAL块和线性化回MAL块。线性化顺序被一个递归调用的从支撑点遍历树的决定。为了说明,考虑下列代码块:
1 2 3 4 5 6 7 8 9 10 11 12 | |
这产生一个目的查询计划的结构
1 2 3 4 5 6 7 8 9 10 11 | |
任何有效的MAL任务都可以被基于流依赖的树或图结构的视图覆盖,但不是所有的MAL程序都可以从一棵简单的树继承。如,上面的程序块片段被解释为线性的序列不能被表示除非执行指令自身成为操作符节点。然而,因为我们没有增加或者改变根源的MAL程序,qep.progagate任务产生原有的先行次序有优先级的程序。如果,然而,我们进入树的新的指令,它们会被放置到邻近的其它树的节点。对块的流控制给予特殊的关照,因为产生一个查询计划块不是很容易就能环绕。
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 | |
6.范围传播
几乎所有的查询对表中的几个段有兴趣。如果用视图表示,查询计划经常含有对同一个列的选择。它们可能也修补了从碎片标准来的参数。 PUSHRANGES优化器的目的是最小化对表的范围的扫描。除非指令被移出计划。
1 2 3 4 5 6 | |
这么长的序列可以被压缩成一条:
1 2 | |
从同一源码对两个范围的选择的并集可能是一个目标:
1 2 3 | |
会变为:
1
| |
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 | |
7.循环再生器
在现有的数据库系统中查询优化和处理经常仍集中在各自的查询。查询分开地被分析和和内核赛跑不管并行或之前的调用提供的机遇。这种方法远离最优和两个方向被发现可以改善:物理化视图和(部分)结果集重使用。物理化视图从查询日志中继承。它们代表公共的子查询,其物理化改善接下来查询时间。重用部分结果被用于放大或导航应用处于危急关头的情况。循环再生优化器和模块扩展这with a middle out approach.它们利用MonetDB的materialize-all-intermediate方法来决定保留它们只要被认为有利。
采用的方法是在MAL程序中使用recycler优化器调用标记指令,以至它们的结果被保留在一个全局的再生寄宿于MAL解析器的缓冲。指令受Recycler管制如果至少它其中一个参数是BAT和其他不是常数或者变量,且在Recycler已知。在运行的时候,在没有代价下,Recycler被MAL解析器最里层的循环调用去检查一个更新的会被保留的结果。否则,它计算指令和调用policy functions去决定是否这值得保留。
Recycler有几个policy控制操作在具体的设置下实验它的效果。retain policy控制什么时候保留结果,reuse policy照看具体复制的指令或者使用语义知识在MAL指令去探测潜在的使用(例如,重用select 结果)。最后,cache policy照管中间结果pool的存储空间。具体的细节在重用模块描述:
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 298 299 300 301 302 303 | |