Ai audio gen for long written formats
One of my biggest weaknesses is that I tend to lose focus when reading long-form content like technical blog posts, documentation, and worst of all, books. As much as I’d love to absorb all that knowledge and wisdom, most of the time, I just can’t get through them.
On the other hand, I’m a big consumer of audio and video content, whether it’s audiobooks, video formats like walkthroughs, speeches, presentations, or podcasts. I just play them in the background, normally at 1.5x or 2x speed.
With recent advancements in AI, I think I have found a good middle ground for this weakness. I use tools like Google’s NotebookLM to summarize and study long formats like books and generate podcast-style audio conversations, and ElevenLabs’ ElevenReader to get natural audio readings of blogs. Although I recognize that deeply understanding some content requires going through it on your own, getting even 10% from these resources while doing other things is a no-brainer.
Here are some examples from my NotebookLM library (I may use this as an index for resources I find interesting in the future):
Books
SQL Performance Explained
Summary of Database Indexing Best Practices
This guide outlines key “DOs” and “DON’Ts” for creating and using database indexes effectively to improve query performance. The principles cover everything from simple lookups to complex joins, sorting, and data modification.
1. Indexing for Equality Lookups
DO: Use Primary Keys for fast, unique lookups.
A query filtering on aPRIMARY KEY
is extremely fast because the database can perform a direct lookup (INDEX UNIQUE SCAN
).DON’T: Assume a Primary Key always results in the fastest possible scan (Oracle-specific).
If a primary key is backed by a non-unique index (used for special cases like deferrable constraints), Oracle will use a slightly slowerINDEX RANGE SCAN
instead of anINDEX UNIQUE SCAN
.2. Concatenated (Multi-Column) Indexes
DO: Order columns in an index based on how you query them.
Place columns used inWHERE
clauses with equality checks first. This allows the index to be used efficiently.DON’T: Use an incorrect column order in your index.
If your query doesn’t filter on the first column of a multi-column index, the database cannot use the index effectively and may have to scan the entire table.3. Using Functions in
WHERE
Clauses
DON’T: Apply functions to indexed columns.
Using a function likeUPPER()
on an indexed column prevents the database from using the index, forcing a full table scan.DO: Create a Function-Based Index to match the function in your query.
If you must use a function, create an index on that exact function expression.4. Parameterized Queries (“Bind Variables”)
DO: Use bind parameters to improve security and performance.
Bind parameters prevent SQL injection and allow the database to reuse query execution plans, saving time.DON’T: Use “smart logic” with
**OR**
to build optional filters.
This anti-pattern creates a one-size-fits-all query that performs poorly because the database cannot use indexes for the optional conditions.DO: Use Dynamic SQL for optional search criteria.
Build the SQL query in your application code, addingWHERE
clauses only for the parameters provided. This allows the database to create a highly efficient plan for each specific search.5. Join Operations
DON’T: Fall into the “N+1 Selects” trap from ORMs.
Fetching a list of items and then looping through them to fetch related data generates many slow, individual database queries.**DO: Use explicit **
**JOIN**
s to fetch related data in a single query.
Configure your ORM for eager fetching or write aJOIN
statement. This is vastly more efficient as it is only one round trip to the database.6. Data Clustering and Covering Indexes
DO: Create “Covering Indexes” to avoid table access entirely.
If an index contains all the columns needed for a query (in both theSELECT
andWHERE
clauses), the database can answer the query from the index alone (INDEX-ONLY SCAN
), which is extremely fast.DON’T: Use
**SELECT ***
if you want a covering index to work.SELECT *
forces the database to fetch all columns, which are likely not all in your index. This requires an extra step to access the table, defeating the purpose of a covering index.DON’T: Create too many indexes.
While indexes speed up reads, they slow down writes (INSERT
,UPDATE
,DELETE
) because every index must be updated. Find a good balance.7. Sorting (
ORDER BY
) and Grouping (GROUP BY
)
DO: Index the columns in your
**ORDER BY**
clause.
If an index’s columns and sort order match theORDER BY
clause, the database can read data in the correct order directly from the index, avoiding a slow, memory-intensive sort operation.DO: Index columns in your
**GROUP BY**
clause.
Similar toORDER BY
, an index onGROUP BY
columns allows the database to perform aggregation more efficiently without a separate sorting step.8. Paging Through Results
DON’T: Use the
**OFFSET**
method for deep pagination.
UsingOFFSET
forces the database to scan and discard all the rows you are skipping. This gets progressively slower as you go to later pages.DO: Use the “Seek Method” (or Keyset Pagination) for efficient pagination.
Instead of an offset, use aWHERE
clause to “seek” to the starting point of the next page, using the last value from the previous page. This is consistently fast for every page.