@@ -409,14 +409,14 @@ Since the data isn’t naturally ordered in this way, SQLite must perform
409409additional work to achieve this sort order.
410410
411411- ** Temporary B-Tree** : To sort the results efficiently, SQLite creates a
412- temporary B-tree structure. A B-tree is a self-balancing tree data
413- structure that maintains sorted data and allows for efficient insertion,
414- deletion, and lookup operations. By inserting the result set into this B-
415- tree, SQLite can quickly and efficiently retrieve the data in the desired order.
412+ temporary B-tree structure. A B-tree is a self-balancing tree data structure
413+ that maintains sorted data and allows for efficient insertion, deletion, and
414+ lookup operations. By inserting the result set into this B- tree, SQLite can
415+ quickly and efficiently retrieve the data in the desired order.
416416
417417- ** Why Not an Index?** : The need for a temporary B-tree indicates that there
418- isn’t an existing index that supports the required sort order. This extra
419- step adds overhead, which is why creating an appropriate index can be beneficial.
418+ isn’t an existing index that supports the required sort order. This extra step
419+ adds overhead, which is why creating an appropriate index can be beneficial.
420420
421421Combining all these steps, we get the expected output:
422422
@@ -442,14 +442,14 @@ CREATE INDEX idx_likes_drinker_pref ON LIKES(DRINKER_ID, PREFERENCE);
442442
443443By creating this multi-column index, SQLite can:
444444
445- - ** Avoid Full Table Scans** : With this index, SQLite can avoid a full scan
446- of the ` LIKES ` table. Instead, it can directly jump to the relevant rows
447- using the index, which is more efficient.
445+ - ** Avoid Full Table Scans** : With this index, SQLite can avoid a full scan of
446+ the ` LIKES ` table. Instead, it can directly jump to the relevant rows using
447+ the index, which is more efficient.
448448
449449- ** Optimize Sorting** : The index also covers the ` PREFERENCE ` column, which
450450 means the results can be retrieved in the correct order directly from the
451- index. This eliminates the need for a temporary B-tree, reducing the
452- query’s overall execution time.
451+ index. This eliminates the need for a temporary B-tree, reducing the query’s
452+ overall execution time.
453453
454454{{ responsive(
455455 src="multicolumn-idx.png",
@@ -487,42 +487,42 @@ This new execution plan reflects several optimizations made by SQLite:
487487
4884881 . ** SCAN DRINKER** :
489489
490- - SQLite starts by scanning the ` DRINKER ` table. Since this is a full
491- table scan, it reads each row from the ` DRINKER ` table sequentially.
492- This step makes sense as it’s the starting point of our query, and no
493- filters or constraints are applied to ` DRINKER ` that would allow an
494- index to be used here.
490+ SQLite starts by scanning the ` DRINKER ` table. Since this is a full table
491+ scan, it reads each row from the ` DRINKER ` table sequentially. This step
492+ makes sense as it’s the starting point of our query, and no filters or
493+ constraints are applied to ` DRINKER ` that would allow an index to be used
494+ here.
495495
4964962 . ** SEARCH LIKES USING INDEX ` idx_likes_drinker_pref ` (DRINKER_ID=?)** :
497497
498- - Here’s where the optimization kicks in. SQLite uses the newly created
499- index ` idx_likes_drinker_pref ` on the ` LIKES ` table. This index is likely
500- created on the ` DRINKER_ID ` and ` PREFERENCE ` columns, allowing SQLite to
501- efficiently find the rows in ` LIKES ` where ` DRINKER_ID ` matches the
502- current row from the ` DRINKER ` table. This dramatically reduces the amount
503- of data SQLite needs to sift through compared to a full table scan.
498+ Here’s where the optimization kicks in. SQLite uses the newly created index
499+ ` idx_likes_drinker_pref ` on the ` LIKES ` table. This index is likely created
500+ on the ` DRINKER_ID ` and ` PREFERENCE ` columns, allowing SQLite to efficiently
501+ find the rows in ` LIKES ` where ` DRINKER_ID ` matches the current row from the
502+ ` DRINKER ` table. This dramatically reduces the amount of data SQLite needs to
503+ sift through compared to a full table scan.
504504
5055053 . ** SEARCH BEER USING INTEGER PRIMARY KEY (rowid=?)** :
506506
507- - For the ` BEER ` table, SQLite utilizes the primary key index, which is an
508- automatically created index on the ` ID ` column (which acts as the ` rowid ` ).
509- Since this is the most efficient way to retrieve specific rows from ` BEER ` ,
510- SQLite uses this index to quickly find the beer names corresponding to the
511- ` BEER_ID ` values from the ` LIKES ` table.
507+ For the ` BEER ` table, SQLite utilizes the primary key index, which is an
508+ automatically created index on the ` ID ` column (which acts as the ` rowid ` ).
509+ Since this is the most efficient way to retrieve specific rows from ` BEER ` ,
510+ SQLite uses this index to quickly find the beer names corresponding to the
511+ ` BEER_ID ` values from the ` LIKES ` table.
512512
5135134 . ** USE TEMP B-TREE FOR ORDER BY** :
514- - Finally, SQLite notes that it will use a temporary B-Tree to sort the
515- results according to the ` ORDER BY ` clause ( ` DRINKER.NAME ` and
516- ` LIKES.PREFERENCE ` ). Even though indexes can often help with sorting, in
517- this case, SQLite decides to use a temporary B-Tree structure to ensure
518- that the results are returned in the correct order. This step can be a bit
519- more resource-intensive, but it guarantees that the results will be sorted
520- as requested.
514+
515+ Finally, SQLite notes that it will use a temporary B-Tree to sort the results
516+ according to the ` ORDER BY ` clause ( ` DRINKER.NAME ` and ` LIKES.PREFERENCE ` ).
517+ Even though indexes can often help with sorting, in this case, SQLite decides
518+ to use a temporary B-Tree structure to ensure that the results are returned
519+ in the correct order. This step can be a bit more resource-intensive, but it
520+ guarantees that the results will be sorted as requested.
521521
522522The use of the ` idx_likes_drinker_pref ` index significantly improves the
523523efficiency of the query. By avoiding a full table scan on ` LIKES ` , SQLite
524- reduces the amount of data it needs to process, which speeds up query
525- execution, especially on larger datasets.
524+ reduces the amount of data it needs to process, which speeds up query execution,
525+ especially on larger datasets.
526526
527527The final ` ORDER BY ` clause requires SQLite to sort the results, and since
528528the current indexes do not cover both ` DRINKER.NAME ` and ` LIKES.PREFERENCE ` ,
@@ -538,19 +538,19 @@ By peeking under the hood at how SQL queries are executed, you can gain some
538538intuition on why certain queries are faster than others. Here are a few tips
539539to keep in mind:
540540
541- 1 . ** Index Your Foreign Keys** : Always create indexes on columns used in
542- ` JOIN ` conditions. This speeds up the process of matching rows between tables.
541+ 1 . ** Index Your Foreign Keys** : Always create indexes on columns used in ` JOIN `
542+ conditions. This speeds up the process of matching rows between tables.
543543
5445442 . ** Use Covering Indexes** : If possible, create indexes that cover all the
545- columns your query needs, so SQLite doesn’t need to access the main table
546- at all.
545+ columns your query needs, so SQLite doesn’t need to access the main table at
546+ all.
547547
5485483 . ** Write Selective WHERE Clauses** : If your ` WHERE ` clause can quickly
549549 eliminate rows from consideration, your query will run faster. The fewer rows
550550 SQLite has to process, the better.
551551
552- 4 . ** Avoid Redundant Sorting** : If you know your data is already sorted in
553- the way you want, avoid using ` ORDER BY ` . It just adds unnecessary processing
552+ 4 . ** Avoid Redundant Sorting** : If you know your data is already sorted in the
553+ way you want, avoid using ` ORDER BY ` . It just adds unnecessary processing
554554 time.
555555
5565565 . ** Optimize Subqueries** : Subqueries can sometimes be rewritten as joins,
@@ -563,10 +563,10 @@ to keep in mind:
563563
564564Learning to write efficient SQL queries is a valuable skill that translates
565565across all database systems and can make a significant difference in your
566- application’s performance, scalability, and resource usage. Like most things,
567- it takes practice and experimentation and this post just scratches the
568- surface of optimizing queries. If you have any tips or tricks for optimizing
569- SQL queries, feel free to share them in the comments!
566+ application’s performance, scalability, and resource usage. Like most things, it
567+ takes practice and experimentation and this post just scratches the surface of
568+ optimizing queries. If you have any tips or tricks for optimizing SQL queries,
569+ feel free to share them in the comments!
570570
571571## References
572572
0 commit comments