github.com/cockroachdb/cockroach@v20.2.0-alpha.1+incompatible/pkg/sql/opt/testutils/opttester/testdata/opt-steps (about) 1 optsteps 2 SELECT 1 3 ---- 4 ================================================================================ 5 Initial expression 6 Cost: 0.05 7 ================================================================================ 8 project 9 ├── columns: "?column?":1(int!null) 10 ├── cardinality: [1 - 1] 11 ├── key: () 12 ├── fd: ()-->(1) 13 ├── values 14 │ ├── cardinality: [1 - 1] 15 │ ├── key: () 16 │ └── tuple [type=tuple] 17 └── projections 18 └── const: 1 [as="?column?":1, type=int] 19 ================================================================================ 20 MergeProjectWithValues 21 Cost: 0.02 22 ================================================================================ 23 -project 24 +values 25 ├── columns: "?column?":1(int!null) 26 ├── cardinality: [1 - 1] 27 ├── key: () 28 ├── fd: ()-->(1) 29 - ├── values 30 - │ ├── cardinality: [1 - 1] 31 - │ ├── key: () 32 - │ └── tuple [type=tuple] 33 - └── projections 34 - └── const: 1 [as="?column?":1, type=int] 35 + └── tuple [type=tuple{int}] 36 + └── const: 1 [type=int] 37 ================================================================================ 38 Final best expression 39 Cost: 0.02 40 ================================================================================ 41 values 42 ├── columns: "?column?":1(int!null) 43 ├── cardinality: [1 - 1] 44 ├── key: () 45 ├── fd: ()-->(1) 46 └── tuple [type=tuple{int}] 47 └── const: 1 [type=int] 48 49 exec-ddl 50 CREATE TABLE ab (a INT PRIMARY KEY, b INT, INDEX(b)) 51 ---- 52 53 optsteps 54 SELECT * FROM ab WHERE b=1 55 ---- 56 ================================================================================ 57 Initial expression 58 Cost: 1050.03 59 ================================================================================ 60 select 61 ├── columns: a:1(int!null) b:2(int!null) 62 ├── key: (1) 63 ├── fd: ()-->(2) 64 ├── scan ab 65 │ ├── columns: a:1(int!null) b:2(int) 66 │ ├── key: (1) 67 │ └── fd: (1)-->(2) 68 └── filters 69 └── eq [type=bool, outer=(2), constraints=(/2: [/1 - /1]; tight), fd=()-->(2)] 70 ├── variable: b:2 [type=int] 71 └── const: 1 [type=int] 72 -------------------------------------------------------------------------------- 73 GenerateIndexScans (higher cost) 74 -------------------------------------------------------------------------------- 75 select 76 ├── columns: a:1(int!null) b:2(int!null) 77 ├── key: (1) 78 ├── fd: ()-->(2) 79 - ├── scan ab 80 + ├── scan ab@secondary 81 │ ├── columns: a:1(int!null) b:2(int) 82 │ ├── key: (1) 83 │ └── fd: (1)-->(2) 84 └── filters 85 └── eq [type=bool, outer=(2), constraints=(/2: [/1 - /1]; tight), fd=()-->(2)] 86 ├── variable: b:2 [type=int] 87 └── const: 1 [type=int] 88 -------------------------------------------------------------------------------- 89 GenerateZigzagJoins (no changes) 90 -------------------------------------------------------------------------------- 91 ================================================================================ 92 GenerateConstrainedScans 93 Cost: 10.41 94 ================================================================================ 95 -select 96 +scan ab@secondary 97 ├── columns: a:1(int!null) b:2(int!null) 98 + ├── constraint: /2/1: [/1 - /1] 99 ├── key: (1) 100 - ├── fd: ()-->(2) 101 - ├── scan ab 102 - │ ├── columns: a:1(int!null) b:2(int) 103 - │ ├── key: (1) 104 - │ └── fd: (1)-->(2) 105 - └── filters 106 - └── eq [type=bool, outer=(2), constraints=(/2: [/1 - /1]; tight), fd=()-->(2)] 107 - ├── variable: b:2 [type=int] 108 - └── const: 1 [type=int] 109 + └── fd: ()-->(2) 110 ================================================================================ 111 Final best expression 112 Cost: 10.41 113 ================================================================================ 114 scan ab@secondary 115 ├── columns: a:1(int!null) b:2(int!null) 116 ├── constraint: /2/1: [/1 - /1] 117 ├── key: (1) 118 └── fd: ()-->(2) 119 120 exec-ddl 121 CREATE TABLE customers ( 122 id INT8 NOT NULL, 123 name STRING NOT NULL, 124 address STRING NULL, 125 CONSTRAINT "primary" PRIMARY KEY (id ASC), 126 FAMILY "primary" (id, name, address) 127 ) 128 ---- 129 130 exec-ddl 131 CREATE TABLE orders ( 132 id INT8 NOT NULL, 133 customer_id INT8 NULL, 134 status STRING NOT NULL, 135 CONSTRAINT "primary" PRIMARY KEY (id ASC), 136 CONSTRAINT fk_customer_id_ref_customers FOREIGN KEY (customer_id) REFERENCES customers(id), 137 INDEX orders_auto_index_fk_customer_id_ref_customers (customer_id ASC), 138 FAMILY "primary" (id, customer_id, status), 139 CONSTRAINT check_status CHECK (status IN ('open':::STRING, 'complete':::STRING, 'cancelled':::STRING)) 140 ) 141 ---- 142 143 # Verify that we don't crash when a normalization rule runs on a constraint 144 # expression that is attached to the TableMeta but otherwise not used. 145 # In this example, the rule is NormalizeInConst. 146 optsteps 147 SELECT * FROM orders LEFT JOIN customers ON customer_id = customers.id 148 ---- 149 ================================================================================ 150 Initial expression 151 Cost: 2160.05 152 ================================================================================ 153 left-join (hash) 154 ├── columns: id:1(int!null) customer_id:2(int) status:3(string!null) id:4(int) name:5(string) address:6(string) 155 ├── key: (1) 156 ├── fd: (1)-->(2-6), (4)-->(5,6) 157 ├── scan orders 158 │ ├── columns: orders.id:1(int!null) customer_id:2(int) status:3(string!null) 159 │ ├── check constraint expressions 160 │ │ └── in [type=bool, outer=(3), constraints=(/3: [/'cancelled' - /'cancelled'] [/'complete' - /'complete'] [/'open' - /'open']; tight)] 161 │ │ ├── variable: status:3 [type=string] 162 │ │ └── tuple [type=tuple{string, string, string}] 163 │ │ ├── const: 'open' [type=string] 164 │ │ ├── const: 'complete' [type=string] 165 │ │ └── const: 'cancelled' [type=string] 166 │ ├── key: (1) 167 │ └── fd: (1)-->(2,3) 168 ├── scan customers 169 │ ├── columns: customers.id:4(int!null) name:5(string!null) address:6(string) 170 │ ├── key: (4) 171 │ └── fd: (4)-->(5,6) 172 └── filters 173 └── eq [type=bool, outer=(2,4), constraints=(/2: (/NULL - ]; /4: (/NULL - ]), fd=(2)==(4), (4)==(2)] 174 ├── variable: customer_id:2 [type=int] 175 └── variable: customers.id:4 [type=int] 176 ================================================================================ 177 NormalizeInConst 178 Cost: 2160.05 179 ================================================================================ 180 left-join (hash) 181 ├── columns: id:1(int!null) customer_id:2(int) status:3(string!null) id:4(int) name:5(string) address:6(string) 182 ├── key: (1) 183 ├── fd: (1)-->(2-6), (4)-->(5,6) 184 ├── scan orders 185 │ ├── columns: orders.id:1(int!null) customer_id:2(int) status:3(string!null) 186 │ ├── check constraint expressions 187 │ │ └── in [type=bool, outer=(3), constraints=(/3: [/'cancelled' - /'cancelled'] [/'complete' - /'complete'] [/'open' - /'open']; tight)] 188 │ │ ├── variable: status:3 [type=string] 189 │ │ └── tuple [type=tuple{string, string, string}] 190 - │ │ ├── const: 'open' [type=string] 191 + │ │ ├── const: 'cancelled' [type=string] 192 │ │ ├── const: 'complete' [type=string] 193 - │ │ └── const: 'cancelled' [type=string] 194 + │ │ └── const: 'open' [type=string] 195 │ ├── key: (1) 196 │ └── fd: (1)-->(2,3) 197 ├── scan customers 198 │ ├── columns: customers.id:4(int!null) name:5(string!null) address:6(string) 199 │ ├── key: (4) 200 │ └── fd: (4)-->(5,6) 201 └── filters 202 └── eq [type=bool, outer=(2,4), constraints=(/2: (/NULL - ]; /4: (/NULL - ]), fd=(2)==(4), (4)==(2)] 203 ├── variable: customer_id:2 [type=int] 204 └── variable: customers.id:4 [type=int] 205 -------------------------------------------------------------------------------- 206 GenerateIndexScans (no changes) 207 -------------------------------------------------------------------------------- 208 -------------------------------------------------------------------------------- 209 GenerateIndexScans (no changes) 210 -------------------------------------------------------------------------------- 211 -------------------------------------------------------------------------------- 212 CommuteLeftJoin (higher cost) 213 -------------------------------------------------------------------------------- 214 -left-join (hash) 215 +right-join (hash) 216 ├── columns: id:1(int!null) customer_id:2(int) status:3(string!null) id:4(int) name:5(string) address:6(string) 217 ├── key: (1) 218 ├── fd: (1)-->(2-6), (4)-->(5,6) 219 + ├── scan customers 220 + │ ├── columns: customers.id:4(int!null) name:5(string!null) address:6(string) 221 + │ ├── key: (4) 222 + │ └── fd: (4)-->(5,6) 223 ├── scan orders 224 │ ├── columns: orders.id:1(int!null) customer_id:2(int) status:3(string!null) 225 │ ├── check constraint expressions 226 │ │ └── in [type=bool, outer=(3), constraints=(/3: [/'cancelled' - /'cancelled'] [/'complete' - /'complete'] [/'open' - /'open']; tight)] 227 │ │ ├── variable: status:3 [type=string] 228 │ │ └── tuple [type=tuple{string, string, string}] 229 │ │ ├── const: 'cancelled' [type=string] 230 │ │ ├── const: 'complete' [type=string] 231 │ │ └── const: 'open' [type=string] 232 │ ├── key: (1) 233 │ └── fd: (1)-->(2,3) 234 - ├── scan customers 235 - │ ├── columns: customers.id:4(int!null) name:5(string!null) address:6(string) 236 - │ ├── key: (4) 237 - │ └── fd: (4)-->(5,6) 238 └── filters 239 └── eq [type=bool, outer=(2,4), constraints=(/2: (/NULL - ]; /4: (/NULL - ]), fd=(2)==(4), (4)==(2)] 240 ├── variable: customer_id:2 [type=int] 241 └── variable: customers.id:4 [type=int] 242 -------------------------------------------------------------------------------- 243 GenerateMergeJoins (no changes) 244 -------------------------------------------------------------------------------- 245 -------------------------------------------------------------------------------- 246 GenerateLookupJoins (higher cost) 247 -------------------------------------------------------------------------------- 248 -left-join (hash) 249 +left-join (lookup customers) 250 ├── columns: id:1(int!null) customer_id:2(int) status:3(string!null) id:4(int) name:5(string) address:6(string) 251 + ├── key columns: [2] = [4] 252 + ├── lookup columns are key 253 ├── key: (1) 254 ├── fd: (1)-->(2-6), (4)-->(5,6) 255 ├── scan orders 256 │ ├── columns: orders.id:1(int!null) customer_id:2(int) status:3(string!null) 257 │ ├── check constraint expressions 258 │ │ └── in [type=bool, outer=(3), constraints=(/3: [/'cancelled' - /'cancelled'] [/'complete' - /'complete'] [/'open' - /'open']; tight)] 259 │ │ ├── variable: status:3 [type=string] 260 │ │ └── tuple [type=tuple{string, string, string}] 261 │ │ ├── const: 'cancelled' [type=string] 262 │ │ ├── const: 'complete' [type=string] 263 │ │ └── const: 'open' [type=string] 264 │ ├── key: (1) 265 │ └── fd: (1)-->(2,3) 266 - ├── scan customers 267 - │ ├── columns: customers.id:4(int!null) name:5(string!null) address:6(string) 268 - │ ├── key: (4) 269 - │ └── fd: (4)-->(5,6) 270 - └── filters 271 - └── eq [type=bool, outer=(2,4), constraints=(/2: (/NULL - ]; /4: (/NULL - ]), fd=(2)==(4), (4)==(2)] 272 - ├── variable: customer_id:2 [type=int] 273 - └── variable: customers.id:4 [type=int] 274 + └── filters (true) 275 -------------------------------------------------------------------------------- 276 GenerateMergeJoins (higher cost) 277 -------------------------------------------------------------------------------- 278 -left-join (lookup customers) 279 +right-join (merge) 280 ├── columns: id:1(int!null) customer_id:2(int) status:3(string!null) id:4(int) name:5(string) address:6(string) 281 - ├── key columns: [2] = [4] 282 - ├── lookup columns are key 283 + ├── left ordering: +4 284 + ├── right ordering: +2 285 ├── key: (1) 286 ├── fd: (1)-->(2-6), (4)-->(5,6) 287 - ├── scan orders 288 + ├── scan customers 289 + │ ├── columns: customers.id:4(int!null) name:5(string!null) address:6(string) 290 + │ ├── key: (4) 291 + │ ├── fd: (4)-->(5,6) 292 + │ └── ordering: +4 293 + ├── sort 294 │ ├── columns: orders.id:1(int!null) customer_id:2(int) status:3(string!null) 295 - │ ├── check constraint expressions 296 - │ │ └── in [type=bool, outer=(3), constraints=(/3: [/'cancelled' - /'cancelled'] [/'complete' - /'complete'] [/'open' - /'open']; tight)] 297 - │ │ ├── variable: status:3 [type=string] 298 - │ │ └── tuple [type=tuple{string, string, string}] 299 - │ │ ├── const: 'cancelled' [type=string] 300 - │ │ ├── const: 'complete' [type=string] 301 - │ │ └── const: 'open' [type=string] 302 │ ├── key: (1) 303 - │ └── fd: (1)-->(2,3) 304 + │ ├── fd: (1)-->(2,3) 305 + │ ├── ordering: +2 306 + │ └── scan orders 307 + │ ├── columns: orders.id:1(int!null) customer_id:2(int) status:3(string!null) 308 + │ ├── check constraint expressions 309 + │ │ └── in [type=bool, outer=(3), constraints=(/3: [/'cancelled' - /'cancelled'] [/'complete' - /'complete'] [/'open' - /'open']; tight)] 310 + │ │ ├── variable: status:3 [type=string] 311 + │ │ └── tuple [type=tuple{string, string, string}] 312 + │ │ ├── const: 'cancelled' [type=string] 313 + │ │ ├── const: 'complete' [type=string] 314 + │ │ └── const: 'open' [type=string] 315 + │ ├── key: (1) 316 + │ └── fd: (1)-->(2,3) 317 └── filters (true) 318 ================================================================================ 319 Final best expression 320 Cost: 2160.05 321 ================================================================================ 322 left-join (hash) 323 ├── columns: id:1(int!null) customer_id:2(int) status:3(string!null) id:4(int) name:5(string) address:6(string) 324 ├── key: (1) 325 ├── fd: (1)-->(2-6), (4)-->(5,6) 326 ├── scan orders 327 │ ├── columns: orders.id:1(int!null) customer_id:2(int) status:3(string!null) 328 │ ├── check constraint expressions 329 │ │ └── in [type=bool, outer=(3), constraints=(/3: [/'cancelled' - /'cancelled'] [/'complete' - /'complete'] [/'open' - /'open']; tight)] 330 │ │ ├── variable: status:3 [type=string] 331 │ │ └── tuple [type=tuple{string, string, string}] 332 │ │ ├── const: 'cancelled' [type=string] 333 │ │ ├── const: 'complete' [type=string] 334 │ │ └── const: 'open' [type=string] 335 │ ├── key: (1) 336 │ └── fd: (1)-->(2,3) 337 ├── scan customers 338 │ ├── columns: customers.id:4(int!null) name:5(string!null) address:6(string) 339 │ ├── key: (4) 340 │ └── fd: (4)-->(5,6) 341 └── filters 342 └── eq [type=bool, outer=(2,4), constraints=(/2: (/NULL - ]; /4: (/NULL - ]), fd=(2)==(4), (4)==(2)] 343 ├── variable: customer_id:2 [type=int] 344 └── variable: customers.id:4 [type=int] 345 346 exec-ddl 347 CREATE TABLE comp ( 348 k INT, 349 c BOOL AS (k IN (1,3,2)) STORED, 350 INDEX (c, k) 351 ) 352 ---- 353 354 # Verify that we don't crash when a normalization rule runs on a computed 355 # column expression that is attached to the TableMeta but otherwise not used. 356 # In this example, the rule is NormalizeInConst. 357 optsteps 358 SELECT * FROM comp WHERE k=1 359 ---- 360 ================================================================================ 361 Initial expression 362 Cost: 1070.14 363 ================================================================================ 364 project 365 ├── columns: k:1(int!null) c:2(bool) 366 ├── fd: ()-->(1) 367 └── select 368 ├── columns: k:1(int!null) c:2(bool) rowid:3(int!null) 369 ├── key: (3) 370 ├── fd: ()-->(1), (3)-->(2) 371 ├── scan comp 372 │ ├── columns: k:1(int) c:2(bool) rowid:3(int!null) 373 │ ├── computed column expressions 374 │ │ └── c:2 375 │ │ └── in [type=bool] 376 │ │ ├── variable: k:1 [type=int] 377 │ │ └── tuple [type=tuple{int, int, int}] 378 │ │ ├── const: 1 [type=int] 379 │ │ ├── const: 3 [type=int] 380 │ │ └── const: 2 [type=int] 381 │ ├── key: (3) 382 │ └── fd: (3)-->(1,2) 383 └── filters 384 └── eq [type=bool, outer=(1), constraints=(/1: [/1 - /1]; tight), fd=()-->(1)] 385 ├── variable: k:1 [type=int] 386 └── const: 1 [type=int] 387 ================================================================================ 388 NormalizeInConst 389 Cost: 1070.14 390 ================================================================================ 391 project 392 ├── columns: k:1(int!null) c:2(bool) 393 ├── fd: ()-->(1) 394 └── select 395 ├── columns: k:1(int!null) c:2(bool) rowid:3(int!null) 396 ├── key: (3) 397 ├── fd: ()-->(1), (3)-->(2) 398 ├── scan comp 399 │ ├── columns: k:1(int) c:2(bool) rowid:3(int!null) 400 │ ├── computed column expressions 401 │ │ └── c:2 402 │ │ └── in [type=bool] 403 │ │ ├── variable: k:1 [type=int] 404 │ │ └── tuple [type=tuple{int, int, int}] 405 │ │ ├── const: 1 [type=int] 406 - │ │ ├── const: 3 [type=int] 407 - │ │ └── const: 2 [type=int] 408 + │ │ ├── const: 2 [type=int] 409 + │ │ └── const: 3 [type=int] 410 │ ├── key: (3) 411 │ └── fd: (3)-->(1,2) 412 └── filters 413 └── eq [type=bool, outer=(1), constraints=(/1: [/1 - /1]; tight), fd=()-->(1)] 414 ├── variable: k:1 [type=int] 415 └── const: 1 [type=int] 416 ================================================================================ 417 PruneSelectCols 418 Cost: 1060.14 419 ================================================================================ 420 project 421 ├── columns: k:1(int!null) c:2(bool) 422 ├── fd: ()-->(1) 423 └── select 424 - ├── columns: k:1(int!null) c:2(bool) rowid:3(int!null) 425 - ├── key: (3) 426 - ├── fd: ()-->(1), (3)-->(2) 427 + ├── columns: k:1(int!null) c:2(bool) 428 + ├── fd: ()-->(1) 429 ├── scan comp 430 - │ ├── columns: k:1(int) c:2(bool) rowid:3(int!null) 431 - │ ├── computed column expressions 432 - │ │ └── c:2 433 - │ │ └── in [type=bool] 434 - │ │ ├── variable: k:1 [type=int] 435 - │ │ └── tuple [type=tuple{int, int, int}] 436 - │ │ ├── const: 1 [type=int] 437 - │ │ ├── const: 2 [type=int] 438 - │ │ └── const: 3 [type=int] 439 - │ ├── key: (3) 440 - │ └── fd: (3)-->(1,2) 441 + │ ├── columns: k:1(int) c:2(bool) 442 + │ └── computed column expressions 443 + │ └── c:2 444 + │ └── in [type=bool] 445 + │ ├── variable: k:1 [type=int] 446 + │ └── tuple [type=tuple{int, int, int}] 447 + │ ├── const: 1 [type=int] 448 + │ ├── const: 2 [type=int] 449 + │ └── const: 3 [type=int] 450 └── filters 451 └── eq [type=bool, outer=(1), constraints=(/1: [/1 - /1]; tight), fd=()-->(1)] 452 ├── variable: k:1 [type=int] 453 └── const: 1 [type=int] 454 ================================================================================ 455 EliminateProject 456 Cost: 1060.03 457 ================================================================================ 458 -project 459 +select 460 ├── columns: k:1(int!null) c:2(bool) 461 ├── fd: ()-->(1) 462 - └── select 463 - ├── columns: k:1(int!null) c:2(bool) 464 - ├── fd: ()-->(1) 465 - ├── scan comp 466 - │ ├── columns: k:1(int) c:2(bool) 467 - │ └── computed column expressions 468 - │ └── c:2 469 - │ └── in [type=bool] 470 - │ ├── variable: k:1 [type=int] 471 - │ └── tuple [type=tuple{int, int, int}] 472 - │ ├── const: 1 [type=int] 473 - │ ├── const: 2 [type=int] 474 - │ └── const: 3 [type=int] 475 - └── filters 476 - └── eq [type=bool, outer=(1), constraints=(/1: [/1 - /1]; tight), fd=()-->(1)] 477 - ├── variable: k:1 [type=int] 478 - └── const: 1 [type=int] 479 + ├── scan comp 480 + │ ├── columns: k:1(int) c:2(bool) 481 + │ └── computed column expressions 482 + │ └── c:2 483 + │ └── in [type=bool] 484 + │ ├── variable: k:1 [type=int] 485 + │ └── tuple [type=tuple{int, int, int}] 486 + │ ├── const: 1 [type=int] 487 + │ ├── const: 2 [type=int] 488 + │ └── const: 3 [type=int] 489 + └── filters 490 + └── eq [type=bool, outer=(1), constraints=(/1: [/1 - /1]; tight), fd=()-->(1)] 491 + ├── variable: k:1 [type=int] 492 + └── const: 1 [type=int] 493 -------------------------------------------------------------------------------- 494 GenerateIndexScans (higher cost) 495 -------------------------------------------------------------------------------- 496 select 497 ├── columns: k:1(int!null) c:2(bool) 498 ├── fd: ()-->(1) 499 - ├── scan comp 500 - │ ├── columns: k:1(int) c:2(bool) 501 - │ └── computed column expressions 502 - │ └── c:2 503 - │ └── in [type=bool] 504 - │ ├── variable: k:1 [type=int] 505 - │ └── tuple [type=tuple{int, int, int}] 506 - │ ├── const: 1 [type=int] 507 - │ ├── const: 2 [type=int] 508 - │ └── const: 3 [type=int] 509 + ├── scan comp@secondary 510 + │ └── columns: k:1(int) c:2(bool) 511 └── filters 512 └── eq [type=bool, outer=(1), constraints=(/1: [/1 - /1]; tight), fd=()-->(1)] 513 ├── variable: k:1 [type=int] 514 └── const: 1 [type=int] 515 -------------------------------------------------------------------------------- 516 GenerateZigzagJoins (no changes) 517 -------------------------------------------------------------------------------- 518 -------------------------------------------------------------------------------- 519 GenerateConstrainedScans (no changes) 520 -------------------------------------------------------------------------------- 521 ================================================================================ 522 FoldComparison 523 Cost: 10.51 524 ================================================================================ 525 -select 526 +scan comp@secondary 527 ├── columns: k:1(int!null) c:2(bool) 528 - ├── fd: ()-->(1) 529 - ├── scan comp 530 - │ ├── columns: k:1(int) c:2(bool) 531 - │ └── computed column expressions 532 - │ └── c:2 533 - │ └── in [type=bool] 534 - │ ├── variable: k:1 [type=int] 535 - │ └── tuple [type=tuple{int, int, int}] 536 - │ ├── const: 1 [type=int] 537 - │ ├── const: 2 [type=int] 538 - │ └── const: 3 [type=int] 539 - └── filters 540 - └── eq [type=bool, outer=(1), constraints=(/1: [/1 - /1]; tight), fd=()-->(1)] 541 - ├── variable: k:1 [type=int] 542 - └── const: 1 [type=int] 543 + ├── constraint: /2/1/3: [/true/1 - /true/1] 544 + └── fd: ()-->(1) 545 ================================================================================ 546 Final best expression 547 Cost: 10.51 548 ================================================================================ 549 scan comp@secondary 550 ├── columns: k:1(int!null) c:2(bool) 551 ├── constraint: /2/1/3: [/true/1 - /true/1] 552 └── fd: ()-->(1)