Many hyperlinks are disabled.
Use anonymous login
to enable hyperlinks.
Overview
Comment: | Improvements to the query planner to address the inefficiency described by forum post 2568d1f6e6. |
---|---|
Downloads: | Tarball | ZIP archive | SQL archive |
Timelines: | family | ancestors | descendants | both | trunk |
Files: | files | file ages | folders |
SHA3-256: |
72fcc12cda910a0e3f7875eb3d117b2a |
User & Date: | drh 2023-12-23 19:03:50 |
Original Comment: | Improvements to the query planner to address the inefficiency described by [forum/forumpost/2568d1f6e6|forum post 2568d1f6e6]. |
Context
2023-12-24
| ||
11:31 | Avoid signed integer overflow during integrity_check of FTS5. (check-in: 5937df3b user: drh tags: trunk) | |
2023-12-23
| ||
19:03 | Improvements to the query planner to address the inefficiency described by forum post 2568d1f6e6. (check-in: 72fcc12c user: drh tags: trunk) | |
11:31 | Add debugging output routines sqlite3ShowWhereLoop(X) and sqlite3ShowWhereLoopList(X) that can be invoked from a debugger to show a summary of the content of a single WhereLoop object or a list of WhereLoop objects. No change in release builds. (check-in: 5db30bcc user: drh tags: trunk) | |
Changes
Changes to src/where.c.
︙ | ︙ | |||
2426 2427 2428 2429 2430 2431 2432 | sqlite3DbNNFreeNN(db, pWInfo->pMemToFree); pWInfo->pMemToFree = pNext; } sqlite3DbNNFreeNN(db, pWInfo); } /* | | > > > > > > > > > > > > > > > | | | | | | < < < < < < < < < > > > > > > > > > | < | | | | | 2426 2427 2428 2429 2430 2431 2432 2433 2434 2435 2436 2437 2438 2439 2440 2441 2442 2443 2444 2445 2446 2447 2448 2449 2450 2451 2452 2453 2454 2455 2456 2457 2458 2459 2460 2461 2462 2463 2464 2465 2466 2467 2468 2469 2470 2471 2472 2473 2474 2475 2476 2477 2478 2479 2480 2481 2482 2483 2484 2485 2486 2487 2488 2489 2490 2491 2492 2493 | sqlite3DbNNFreeNN(db, pWInfo->pMemToFree); pWInfo->pMemToFree = pNext; } sqlite3DbNNFreeNN(db, pWInfo); } /* ** Return TRUE if X is a proper subset of Y but is of equal or less cost. ** In other words, return true if all constraints of X are also part of Y ** and Y has additional constraints that might speed the search that X lacks ** but the cost of running X is not more than the cost of running Y. ** ** In other words, return true if the cost relationwship between X and Y ** is inverted and needs to be adjusted. ** ** Case 1: ** ** (1a) X and Y use the same index. ** (1b) X has fewer == terms than Y ** (1c) Neither X nor Y use skip-scan ** (1d) X does not have a a greater cost than Y ** ** Case 2: ** ** (2a) X has the same or lower cost, or returns the same or fewer rows, ** than Y. ** (2b) X uses fewer WHERE clause terms than Y ** (2c) Every WHERE clause term used by X is also used by Y ** (2d) X skips at least as many columns as Y ** (2e) If X is a covering index, than Y is too */ static int whereLoopCheaperProperSubset( const WhereLoop *pX, /* First WhereLoop to compare */ const WhereLoop *pY /* Compare against this WhereLoop */ ){ int i, j; if( pX->rRun>pY->rRun && pX->nOut>pY->nOut ) return 0; /* (1d) and (2a) */ assert( (pX->wsFlags & WHERE_VIRTUALTABLE)==0 ); assert( (pY->wsFlags & WHERE_VIRTUALTABLE)==0 ); if( pX->u.btree.nEq < pY->u.btree.nEq /* (1b) */ && pX->u.btree.pIndex==pY->u.btree.pIndex /* (1a) */ && pX->nSkip==0 && pY->nSkip==0 /* (1c) */ ){ return 1; /* Case 1 is true */ } if( pX->nLTerm-pX->nSkip >= pY->nLTerm-pY->nSkip ){ return 0; /* (2b) */ } if( pY->nSkip > pX->nSkip ) return 0; /* (2d) */ for(i=pX->nLTerm-1; i>=0; i--){ if( pX->aLTerm[i]==0 ) continue; for(j=pY->nLTerm-1; j>=0; j--){ if( pY->aLTerm[j]==pX->aLTerm[i] ) break; } if( j<0 ) return 0; /* (2c) */ } if( (pX->wsFlags&WHERE_IDX_ONLY)!=0 && (pY->wsFlags&WHERE_IDX_ONLY)==0 ){ return 0; /* (2e) */ } return 1; /* Case 2 is true */ } /* ** Try to adjust the cost and number of output rows of WhereLoop pTemplate ** upwards or downwards so that: ** ** (1) pTemplate costs less than any other WhereLoops that are a proper |
︙ | ︙ |
Changes to test/where3.test.
︙ | ︙ | |||
487 488 489 490 491 492 493 494 495 496 | do_execsql_test where3-7.$disabled_opt.8 { SELECT x3 FROM t73 LEFT JOIN t74 ON x4=y3; } {123 123} do_execsql_test where3-7.$disabled_opt.9 { SELECT DISTINCT x3 FROM t73 LEFT JOIN t74 ON x4=y3; } {123} } finish_test | > > > > > > > > > > > > > > > > > > > > > > | 487 488 489 490 491 492 493 494 495 496 497 498 499 500 501 502 503 504 505 506 507 508 509 510 511 512 513 514 515 516 517 518 | do_execsql_test where3-7.$disabled_opt.8 { SELECT x3 FROM t73 LEFT JOIN t74 ON x4=y3; } {123 123} do_execsql_test where3-7.$disabled_opt.9 { SELECT DISTINCT x3 FROM t73 LEFT JOIN t74 ON x4=y3; } {123} } # 2023-12-23 # https://sqlite.org/forum/forumpost/2568d1f6e6 # # Index usage should be "x=? and y=?" - equality on both values. # Not: "x=? AND y>?" - inequality on "y" # reset_db do_execsql_test where3-8.1 { CREATE TABLE t1(a,b,c,d); INSERT INTO t1 VALUES(1,2,3,4); CREATE TABLE t2(x,y); INSERT INTO t2 VALUES(3,4); CREATE INDEX t2xy ON t2(x,y); SELECT 1 FROM t1 JOIN t2 ON x=c AND y=d WHERE d>0; } 1 do_eqp_test where3-8.2 { SELECT 1 FROM t1 JOIN t2 ON x=c AND y=d WHERE d>0; } { QUERY PLAN |--SCAN t1 `--SEARCH t2 USING COVERING INDEX t2xy (x=? AND y=?) } finish_test |