github.com/cockroachdb/pebble@v0.0.0-20231214172447-ab4952c5f87b/sstable/testdata/block_properties (about) 1 # The following collectors are available: 2 # - value-first - uses the first character of the value to construct an interval 3 # - value-last - uses the last character of the value to construct an interval 4 # - suffix - constructs an interval from the '@timestamp' suffix of each key 5 # - suffix-point-keys-only - same as "suffix", but only applies to point keys 6 # - suffix-range-keys-only - same as "suffix", but only applies to range keys 7 # - nil-points-and-ranges - a trivial collector with neither a point nor range collector 8 9 # Single collector. 10 11 build collectors=(value-first) 12 a.SET.1:10 13 b.SET.2:20 14 c.SET.3:30 15 ---- 16 point: [a#1,1,c#3,1] 17 rangedel: [#0,0,#0,0] 18 rangekey: [#0,0,#0,0] 19 seqnums: [1,3] 20 21 # collectors returns the collectors used when writing the table, keyed by the 22 # shortID of the collector. 23 collectors 24 ---- 25 0: value-first 26 27 # table-props returns the table-level properties, keyed by the shortID. 28 table-props 29 ---- 30 0: [1, 4) 31 32 # block-props returns the block-level properties. For each block, the separator 33 # is printed, along with the properties for the block, keyed by the shortID. 34 block-props 35 ---- 36 d#72057594037927935,17: 37 0: [1, 4) 38 39 # Multiple collectors. 40 41 build collectors=(value-first,value-last) 42 a.SET.1:17 43 b.SET.2:29 44 c.SET.3:38 45 ---- 46 point: [a#1,1,c#3,1] 47 rangedel: [#0,0,#0,0] 48 rangekey: [#0,0,#0,0] 49 seqnums: [1,3] 50 51 collectors 52 ---- 53 0: value-first 54 1: value-last 55 56 table-props 57 ---- 58 0: [1, 4) 59 1: [7, 10) 60 61 block-props 62 ---- 63 d#72057594037927935,17: 64 0: [1, 4) 65 1: [7, 10) 66 67 # Reduce the block size to a value such that each block has at most two KV 68 # pairs. 69 70 build block-size=25 collectors=(value-first,value-last) 71 a.SET.1:15 72 b.SET.2:86 73 c.SET.3:72 74 d.SET.4:21 75 e.SET.5:47 76 f.SET.6:54 77 g.SET.7:63 78 h.SET.8:38 79 ---- 80 point: [a#1,1,h#8,1] 81 rangedel: [#0,0,#0,0] 82 rangekey: [#0,0,#0,0] 83 seqnums: [1,8] 84 85 collectors 86 ---- 87 0: value-first 88 1: value-last 89 90 table-props 91 ---- 92 0: [1, 9) 93 1: [1, 9) 94 95 block-props 96 ---- 97 b#2,1: 98 0: [1, 9) 99 1: [5, 7) 100 d#4,1: 101 0: [2, 8) 102 1: [1, 3) 103 f#6,1: 104 0: [4, 6) 105 1: [4, 8) 106 i#72057594037927935,17: 107 0: [3, 7) 108 1: [3, 9) 109 110 # Range keys contribute to the table-level property but do not affect point key 111 # data blocks. 112 113 build collectors=(suffix) 114 a@5.SET.1:foo 115 b@10.SET.2:bar 116 c@15.SET.3:baz 117 rangekey: d@10-e@15:{(#4,RANGEKEYSET,@20,foo)} 118 rangekey: e@15-f@20:{(#5,RANGEKEYUNSET,@25)} 119 rangekey: f@20-z@25:{(#6,RANGEKEYDEL)} 120 ---- 121 point: [a@5#1,1,c@15#3,1] 122 rangedel: [#0,0,#0,0] 123 rangekey: [d@10#4,21,z@25#72057594037927935,19] 124 seqnums: [1,6] 125 126 collectors 127 ---- 128 0: suffix 129 130 block-props 131 ---- 132 d#72057594037927935,17: 133 0: [5, 16) 134 135 table-props 136 ---- 137 0: [5, 26) 138 139 # Same as the above, but only collect point key properties. 140 141 build collectors=(suffix-point-keys-only) 142 a@5.SET.1:foo 143 b@10.SET.2:bar 144 c@15.SET.3:baz 145 rangekey: d@10-e@15:{(#4,RANGEKEYSET,@20,foo)} 146 rangekey: e@15-f@20:{(#5,RANGEKEYUNSET,@25)} 147 rangekey: f@20-z@25:{(#6,RANGEKEYDEL)} 148 ---- 149 point: [a@5#1,1,c@15#3,1] 150 rangedel: [#0,0,#0,0] 151 rangekey: [d@10#4,21,z@25#72057594037927935,19] 152 seqnums: [1,6] 153 154 collectors 155 ---- 156 0: suffix-point-keys-only 157 158 block-props 159 ---- 160 d#72057594037927935,17: 161 0: [5, 16) 162 163 table-props 164 ---- 165 0: [5, 16) 166 167 # Same as the above, but only collect range key properties. 168 169 build collectors=(suffix-range-keys-only) 170 a@5.SET.1:foo 171 b@10.SET.2:bar 172 c@15.SET.3:baz 173 rangekey: d@10-e@15:{(#4,RANGEKEYSET,@20,foo)} 174 rangekey: e@15-f@20:{(#5,RANGEKEYUNSET,@25)} 175 rangekey: f@20-z@25:{(#6,RANGEKEYDEL)} 176 ---- 177 point: [a@5#1,1,c@15#3,1] 178 rangedel: [#0,0,#0,0] 179 rangekey: [d@10#4,21,z@25#72057594037927935,19] 180 seqnums: [1,6] 181 182 collectors 183 ---- 184 0: suffix-range-keys-only 185 186 block-props 187 ---- 188 d#72057594037927935,17: 189 190 table-props 191 ---- 192 0: [20, 26) 193 194 # Create a table with multiple data blocks and a range key block. Two block 195 # property collectors are used, one for range keys and one for point keys, each 196 # acting independently. 197 198 build block-size=1 collectors=(suffix-point-keys-only,suffix-range-keys-only) 199 a@5.SET.1:foo 200 b@10.SET.2:bar 201 c@15.SET.3:baz 202 rangekey: d@10-e@15:{(#4,RANGEKEYSET,@20,foo)} 203 rangekey: e@15-f@20:{(#5,RANGEKEYUNSET,@25)} 204 rangekey: f@20-z@25:{(#6,RANGEKEYDEL)} 205 ---- 206 point: [a@5#1,1,c@15#3,1] 207 rangedel: [#0,0,#0,0] 208 rangekey: [d@10#4,21,z@25#72057594037927935,19] 209 seqnums: [1,6] 210 211 collectors 212 ---- 213 0: suffix-point-keys-only 214 1: suffix-range-keys-only 215 216 block-props 217 ---- 218 b#72057594037927935,17: 219 0: [5, 6) 220 c#72057594037927935,17: 221 0: [10, 11) 222 d#72057594037927935,17: 223 0: [15, 16) 224 225 table-props 226 ---- 227 0: [5, 16) 228 1: [20, 26) 229 230 # Partially matching point key filter. 231 232 filter point-filter=(suffix-point-keys-only,10,20) 233 ---- 234 points: true, blocks=[1,2] 235 ranges: true (no filters provided) 236 237 # Non-matching point key filter. 238 239 filter point-filter=(suffix-point-keys-only,100,200) 240 ---- 241 points: false 242 ranges: true (no filters provided) 243 244 # Partially matching range key filter. 245 246 filter range-filter=(suffix-range-keys-only,10,25) 247 ---- 248 points: true (no filters provided) 249 ranges: true 250 251 # Non-matching range key filter. 252 253 filter range-filter=(suffix-range-keys-only,100,200) 254 ---- 255 points: true (no filters provided) 256 ranges: false 257 258 # Matching point and range key filter. 259 260 filter point-filter=(suffix-point-keys-only,10,20) range-filter=(suffix-range-keys-only,10,25) 261 ---- 262 points: true, blocks=[1,2] 263 ranges: true 264 265 # Matching point key filter and non-matching range key filter. 266 267 filter point-filter=(suffix-point-keys-only,10,20) range-filter=(suffix-range-keys-only,100,200) 268 ---- 269 points: true, blocks=[1,2] 270 ranges: false 271 272 # Non-matching point key filter and matching range key filter. 273 274 filter point-filter=(suffix-point-keys-only,100,200) range-filter=(suffix-range-keys-only,10,25) 275 ---- 276 points: false 277 ranges: true 278 279 # Non-matching point and range key filter. 280 281 filter point-filter=(suffix-point-keys-only,100,200) range-filter=(suffix-range-keys-only,100,100) 282 ---- 283 points: false 284 ranges: false 285 286 # Providing a nil collector for both points and ranges is a user-error. 287 288 build collectors=(nil-points-and-ranges) 289 ---- 290 sstable: at least one interval collector must be provided 291 292 # Test a small index-block-size and block-size, so every data block has one KV 293 # and every index block points to one data block. 294 295 build collectors=(suffix-point-keys-only) index-block-size=1 block-size=1 296 a@1.SET.1:foo 297 b@10.SET.2:bar 298 c@15.SET.3:baz 299 d@25.SET.4:bax 300 e@3.SET.5:box 301 f@5.SET.3:mop 302 ---- 303 point: [a@1#1,1,f@5#3,1] 304 rangedel: [#0,0,#0,0] 305 rangekey: [#0,0,#0,0] 306 seqnums: [1,5] 307 308 collectors 309 ---- 310 0: suffix-point-keys-only 311 312 table-props 313 ---- 314 0: [1, 26) 315 316 # Because of the tiny index block size, every index block should have the same 317 # properties as the single data block contained in the table. Indentation shows 318 # the hierarchy. 319 320 block-props 321 ---- 322 b#72057594037927935,17: 323 0: [1, 2) 324 b#72057594037927935,17: 325 0: [1, 2) 326 c#72057594037927935,17: 327 0: [10, 11) 328 c#72057594037927935,17: 329 0: [10, 11) 330 d#72057594037927935,17: 331 0: [15, 16) 332 d#72057594037927935,17: 333 0: [15, 16) 334 e#72057594037927935,17: 335 0: [25, 26) 336 e#72057594037927935,17: 337 0: [25, 26) 338 f#72057594037927935,17: 339 0: [3, 4) 340 f#72057594037927935,17: 341 0: [3, 4) 342 g#72057594037927935,17: 343 0: [5, 6) 344 g#72057594037927935,17: 345 0: [5, 6) 346 347 # Test the same sstable, but with a larger index block size that fits multiple 348 # (3) KV pairs. Each entry in the top-level index should hold the unioned ranges 349 # of all the data blocks' properties. 350 351 build collectors=(suffix-point-keys-only) index-block-size=64 block-size=1 352 a@1.SET.1:foo 353 b@10.SET.2:bar 354 c@15.SET.3:baz 355 d@25.SET.4:bax 356 e@3.SET.5:box 357 f@5.SET.3:mop 358 ---- 359 point: [a@1#1,1,f@5#3,1] 360 rangedel: [#0,0,#0,0] 361 rangekey: [#0,0,#0,0] 362 seqnums: [1,5] 363 364 collectors 365 ---- 366 0: suffix-point-keys-only 367 368 block-props 369 ---- 370 d#72057594037927935,17: 371 0: [1, 16) 372 b#72057594037927935,17: 373 0: [1, 2) 374 c#72057594037927935,17: 375 0: [10, 11) 376 d#72057594037927935,17: 377 0: [15, 16) 378 g#72057594037927935,17: 379 0: [3, 26) 380 e#72057594037927935,17: 381 0: [25, 26) 382 f#72057594037927935,17: 383 0: [3, 4) 384 g#72057594037927935,17: 385 0: [5, 6) 386 387 # Regression test for a bug in boundary checking when skipping over irrelevant 388 # index blocks in a two-level indexed sstable. 389 390 iter lower=a point-key-filter=(suffix-point-keys-only,1,2) 391 seek-lt h 392 last 393 ---- 394 <a@1:1> MaybeFilteredKeys()=true 395 <a@1:1> MaybeFilteredKeys()=true 396 397 # Same as above, but each index block holds 2 keys. This exercises a variant of 398 # the above bug. Specifically, the bounds check performed /within/ skipBackward, 399 # instead of within SeekLT and Last. 400 401 build collectors=(suffix-point-keys-only) index-block-size=48 block-size=1 402 a@1.SET.1:foo 403 b@10.SET.2:bar 404 c@15.SET.3:baz 405 d@25.SET.4:bax 406 e@3.SET.5:box 407 f@5.SET.3:mop 408 ---- 409 point: [a@1#1,1,f@5#3,1] 410 rangedel: [#0,0,#0,0] 411 rangekey: [#0,0,#0,0] 412 seqnums: [1,5] 413 414 block-props 415 ---- 416 c#72057594037927935,17: 417 0: [1, 11) 418 b#72057594037927935,17: 419 0: [1, 2) 420 c#72057594037927935,17: 421 0: [10, 11) 422 e#72057594037927935,17: 423 0: [15, 26) 424 d#72057594037927935,17: 425 0: [15, 16) 426 e#72057594037927935,17: 427 0: [25, 26) 428 g#72057594037927935,17: 429 0: [3, 6) 430 f#72057594037927935,17: 431 0: [3, 4) 432 g#72057594037927935,17: 433 0: [5, 6) 434 435 # Regression test for a bug in boundary checking when skipping over irrelevant 436 # index blocks in a two-level indexed sstable. 437 438 iter lower=a upper=z point-key-filter=(suffix-point-keys-only,1,2) 439 seek-lt h 440 ---- 441 <a@1:1> MaybeFilteredKeys()=true 442 443 # Test MaybeFilteredKeys(). 444 445 # Use timestamp range [1,9), which matches a@1, e@3 and f@5 and filters 446 # a continuous section of three keys b@10, c@15 and d@25. 447 448 iter point-key-filter=(suffix-point-keys-only,1,9) 449 first 450 next 451 next 452 next 453 seek-ge b 454 seek-ge e@3 455 ---- 456 <a@1:1> MaybeFilteredKeys()=false 457 <e@3:5> MaybeFilteredKeys()=true 458 <f@5:3> MaybeFilteredKeys()=false 459 . MaybeFilteredKeys()=false 460 <e@3:5> MaybeFilteredKeys()=true 461 <e@3:5> MaybeFilteredKeys()=false 462 463 464 # NB: `seek-ge e` and `seek-ge dog` return MaybeFilteredKeys()=true, despite no 465 # filtered keys existing within the range [e,e@3) or [dog,e@3). This is a 466 # consequence of the index separator `e`. After seeking the index block, the 467 # iterator only knows that the first block MAY contain keys ≤ e. However, it can 468 # be skipped regardless, because block properties filters exclude it. In this 469 # case, the iterator still returns MaybeFilteredKeys()=true, since keys MAY have 470 # been excluded by the filter. 471 472 iter point-key-filter=(suffix-point-keys-only,1,9) 473 seek-ge e 474 seek-ge dog 475 ---- 476 <e@3:5> MaybeFilteredKeys()=true 477 <e@3:5> MaybeFilteredKeys()=true 478 479 iter point-key-filter=(suffix-point-keys-only,1,100) 480 first 481 next 482 next 483 next 484 next 485 next 486 next 487 seek-lt d 488 seek-ge d 489 ---- 490 <a@1:1> MaybeFilteredKeys()=false 491 <b@10:2> MaybeFilteredKeys()=false 492 <c@15:3> MaybeFilteredKeys()=false 493 <d@25:4> MaybeFilteredKeys()=false 494 <e@3:5> MaybeFilteredKeys()=false 495 <f@5:3> MaybeFilteredKeys()=false 496 . MaybeFilteredKeys()=false 497 <c@15:3> MaybeFilteredKeys()=false 498 <d@25:4> MaybeFilteredKeys()=false 499 500 # [10,16) intersects {b@10, c@15}. 501 502 iter point-key-filter=(suffix-point-keys-only,10,16) 503 last 504 prev 505 prev 506 seek-lt a 507 seek-lt c 508 seek-lt ca 509 seek-lt f 510 seek-lt e 511 seek-lt d 512 ---- 513 <c@15:3> MaybeFilteredKeys()=true 514 <b@10:2> MaybeFilteredKeys()=false 515 . MaybeFilteredKeys()=true 516 . MaybeFilteredKeys()=true 517 <b@10:2> MaybeFilteredKeys()=false 518 <c@15:3> MaybeFilteredKeys()=false 519 <c@15:3> MaybeFilteredKeys()=true 520 <c@15:3> MaybeFilteredKeys()=true 521 <c@15:3> MaybeFilteredKeys()=false 522 523 # Test monotonically increasing bounds optimization, with the first seek 524 # filtering keys. The subsequent seek must not reuse the current iterator 525 # position and improperly returning MaybeFilteredKeys=false when keys were 526 # filtered. 527 528 iter point-key-filter=(suffix-point-keys-only,10,16) 529 set-bounds lower=b upper=ee 530 seek-ge d 531 set-bounds lower=ee upper=g 532 seek-ge ee 533 ---- 534 . MaybeFilteredKeys()=false 535 . MaybeFilteredKeys()=true 536 . MaybeFilteredKeys()=true 537 . MaybeFilteredKeys()=true 538 539 iter point-key-filter=(suffix-point-keys-only,10,16) 540 set-bounds lower=a upper=b 541 seek-ge a 542 set-bounds lower=b upper=e 543 seek-ge b 544 seek-ge bb 545 ---- 546 . MaybeFilteredKeys()=false 547 . MaybeFilteredKeys()=true 548 . MaybeFilteredKeys()=true 549 <b@10:2> MaybeFilteredKeys()=true 550 <c@15:3> MaybeFilteredKeys()=false 551 552 # Test monotonically decreasing bounds optimization, with the first seek 553 # filtering keys. The subsequent seek must not reuse the current iterator 554 # position and improperly returning MaybeFilteredKeys=false when keys were 555 # filtered. 556 557 iter point-key-filter=(suffix-point-keys-only,10,16) 558 set-bounds lower=e upper=f 559 seek-lt f 560 set-bounds lower=c upper=e 561 seek-lt e 562 set-bounds lower=a upper=c 563 seek-lt c 564 seek-lt b 565 ---- 566 . MaybeFilteredKeys()=false 567 . MaybeFilteredKeys()=true 568 . MaybeFilteredKeys()=true 569 <c@15:3> MaybeFilteredKeys()=true 570 . MaybeFilteredKeys()=true 571 <b@10:2> MaybeFilteredKeys()=false 572 . MaybeFilteredKeys()=true 573 574 # The below case tests try-seek-using-next. 575 # 576 # The `seek-ge aa` does not reposition the iterator. This case should preserve 577 # the existing MaybeFilteredKeys()=true value. 578 # 579 # The `seek-ge c@16` and seek-ge c@19` must also return MaybeFilteredKeys()=true. 580 581 iter point-key-filter=(suffix-point-keys-only,10,16) 582 seek-ge a 583 seek-ge aa true 584 seek-ge bb true 585 seek-ge c@16 true 586 seek-ge c@19 true 587 ---- 588 <b@10:2> MaybeFilteredKeys()=true 589 <b@10:2> MaybeFilteredKeys()=true 590 <c@15:3> MaybeFilteredKeys()=false 591 . MaybeFilteredKeys()=true 592 . MaybeFilteredKeys()=true 593 594 # Test another case of monotonically increasing bounds optimization, with a 595 # different index block structure. The first seek down below should filter keys, 596 # and leave the top-level index positioned at the last index block. The 597 # subsequent seek must return MaybeFilteredKeys=true when keys were filtered. 598 599 build collectors=(suffix-point-keys-only) index-block-size=1 block-size=64 600 a@1.SET.1:foo 601 b@10.SET.2:bar 602 c@15.SET.3:baz 603 d@25.SET.4:bax 604 e@3.SET.5:box 605 f@5.SET.3:mop 606 ---- 607 point: [a@1#1,1,f@5#3,1] 608 rangedel: [#0,0,#0,0] 609 rangekey: [#0,0,#0,0] 610 seqnums: [1,5] 611 612 block-props 613 ---- 614 d#72057594037927935,17: 615 0: [1, 16) 616 d#72057594037927935,17: 617 0: [1, 16) 618 g#72057594037927935,17: 619 0: [3, 26) 620 g#72057594037927935,17: 621 0: [3, 26) 622 623 iter point-key-filter=(suffix-point-keys-only,1,2) 624 set-bounds lower=b upper=e 625 seek-ge d 626 set-bounds lower=e upper=g 627 seek-ge ee 628 ---- 629 . MaybeFilteredKeys()=false 630 . MaybeFilteredKeys()=true 631 . MaybeFilteredKeys()=true 632 . MaybeFilteredKeys()=true 633 634 # Test another case of monotonically increasing bounds optimization, with a new 635 # index block structure: This one has only one level. The first seek down below 636 # should filter keys, and leave the index positioned at the last index block. 637 # The subsequent seek must return MaybeFilteredKeys=true when keys were 638 # filtered. 639 640 build collectors=(suffix-point-keys-only) block-size=32 641 a@1.SET.1:foo 642 b@10.SET.2:bar 643 c@15.SET.3:baz 644 d@25.SET.4:bax 645 e@3.SET.5:box 646 f@5.SET.3:mop 647 ---- 648 point: [a@1#1,1,f@5#3,1] 649 rangedel: [#0,0,#0,0] 650 rangekey: [#0,0,#0,0] 651 seqnums: [1,5] 652 653 block-props 654 ---- 655 c#72057594037927935,17: 656 0: [1, 11) 657 e#72057594037927935,17: 658 0: [15, 26) 659 g#72057594037927935,17: 660 0: [3, 6) 661 662 iter point-key-filter=(suffix-point-keys-only,1,2) 663 set-bounds lower=b upper=ee 664 seek-ge d 665 set-bounds lower=ee upper=g 666 seek-ge ee 667 ---- 668 . MaybeFilteredKeys()=false 669 . MaybeFilteredKeys()=true 670 . MaybeFilteredKeys()=true 671 . MaybeFilteredKeys()=true