How does database indexing work? (2008)
stackoverflow.com
stackoverflow.com
And of course, Use the Index Luke is a great reference for the real world.
[0] https://notes.eatonphil.com/database-basics-indexes.html
write a brief binary search algo to search the index.
Compare searching the words with a "table scan" on the first file using grep, vs the binary search on the index.
You will find the table scan is O(n) and your binary search is roughly O(log n)
In 60 minutes you'll understand more about indexing than reading stack overflow.
Lol
His website "Use the Index, Luke!" [1] is also great.
[1] http://www.catb.org/esr/structure-packing/
[2] https://www.postgresql.org/docs/14/storage-page-layout.html
[3] https://docs.gitlab.com/ee/development/ordering_table_column...
https://en.wikipedia-on-ipfs.org/wiki/Database_index
From "Hosting SQLite Databases on GitHub Pages" https://news.ycombinator.com/item?id=28021766 re: edgesearch, HTTP/3 QUIC UDP, :
> Serverless full-text search with Cloudflare Workers, WebAssembly, and Roaring Bitmaps https://github.com/wilsonzlin/edgesearch
>> How it works: Edgesearch builds a reverse index by mapping terms to a compressed bit set (using Roaring Bitmaps) of IDs of documents containing the term, and creates a custom worker script and data to upload to Cloudflare Workers
Binary trees are the ideal in a world of a pure von Neumann model. In practice data structures perform better when data is grouped together and this is what the b-tree gets you. It's both more disk and cache efficient in real world workflows
And..even if you did, you could re-index it.
EDIT: This is no longer true. Thanks latch!
As of 14.1, they still don't support unique constraints:
select amname, pg_indexam_has_property(oid, 'can_unique') from pg_am
amname | pg_indexam_has_property
--------+-------------------------
heap | ¤
btree | t
hash | f
gist | f
gin | f
spgist | f
brin | fFor sorting or adjacency queries, you want a btree index. A hash index can give you O(1) lookup with the drawback that you lose ordering completely (whereas getting a sorted selection of records with a tree is a O(1) operation). The trick here is having a hashing function which is both fast and avoids collisions (the worst case scenario is hash(x)=1 where everything hashes to the same value and you end up again with O(n) lookups).
By definition a binary tree means there are two children per node.
Binary is the one thing a b-tree is not.
This difference occurs because a B-tree can have interior nodes that aren't completely full, whereas a binary tree's interior nodes have exactly 2 children.
Seems like it would be extremely odd to have a 2-2 btree, you’d just get a significantly more complicated BST no?
I’d figure you’d want to fill a cacheline with something typical-ish, so probably at least 4 (this way if you have 4 children and 3 keys, the keys are 8 bytes and the child links are straight pointers your node is 56 bytes and you can add some metadata e.g. a bitmap).
Apparently Rust’s BTreeMap is a 6-11 btree but I don’t know how they picked the branching factor.
A simplified project how indices, for example in b-tree, are stored in segment files.
It doesn't actually match low level implementations for a number of reasons. Such as the need to fix the page size the block fits in rather than the count of things in the block, and locking for concurrent access. But the data structure itself still looks the same.
"Since indices are only used to speed up the searching for a matching field within the records, it stands to reason that indexing fields used only for output would be simply a waste of disk space and processing time when doing an insert or delete operation, and thus should be avoided."
Specifically "indexing fields used only for output", what does this mean? I interpreted it as "indexes used only for `select` statements", but that would see completely counter to the main reason you'd want an index e.g. to speed up record retrieval.
They are just SELECTed, i.e. sent in the output (the query results).
Suppose you have this query:
select a, b
from T
where x = 1
And suppose you have an index on x. You can locate the x=1 INDEX records using the index quickly (probably no more than 1-3 disk accesses). But then the qualifying TABLE records have to be retrieved. That index lookup could turn up thousands of qualifying records, and now you have to retrieve each record to get the a, b values.Now suppose that you replace your index on (x) with an index keyed by (x, a, b). You can still search for x=1 using this index, but now, the (a, b) values that you are SELECTing are present in the index itself. You don't have get the table records to get those values. That can save a lot of random accesses, and there are secondary effects, since the pages containing those records aren't brought into the disk cache.
Yes, this wider index has space and update costs, but the benefit is often worth it.
[1]: https://www.postgresql.org/docs/current/sql-createindex.html
I was teaching a database course a couple of years ago, using Postgres, and in exercises on query optimization, I found it surprisingly difficult to get columns added to indexes to produce a convincing improvement.
(* It depends on the database type. In an LSM-tree layer, the blocks are typically contiguous in a file, so direct binary search is possible, though it might not be the most efficient method. The filesystem handles locating blocks in this case.)
The database table is disk blocks containing data where the blocks are logically in order of keys, as if in a contiguous array. Really they are laid out differently on disk.
So there's a block index, which is just a smaller version of the same table data structure: a table mapping keys to values, implemented as blocks in logical order of keys, as if in a contiguous array. Except in this index, the map is from key-ranges of the first table to block locations on disk. This index lets you go from keys to block locations on disk, and it also lets you do a course-grained version of the binary search to narrow down to a single block of the larger table.
Ok, but then how do you look things up in the block index if it's using the same kind of data structure, made of multiple blocks? Same again: Each block index has its own smaller block index.
This neat recursive definition gives you a tower of progressively smaller block indexes until the size is just one block, which doesn't need an index.
Guess what you get when each table of logically sorted, contiguous blocks has a smaller index to say where the blocks are really located?
The data structure is called a B-tree (technically a B+tree), and the smallest index is the root block.
The tree structure arises from the recursive description, where each table has another table (until it stops).
This is a decidedly non-standard way of describing the B-tree data structure. There's no explicit tree. But it's a valid and useful alternative view. (Note, these block indexes are not what is generally meant by database indexes, and they are not visible at the SQL level. They are an implementation detail.)
One of the useful things to emerge from this view is that each level is just logically a flat table, made of blocks that are logically in key order but have arbitrary physical location. It's not necessary for every index to use the same data structure, or be on the same storage. Depending on how you think about algorithms, this description might be simpler to work with.
Why would I do this? [1]
[0] [https://otter.ai/u/SDndzmSLow_a2rNNzm35ohw4y9w](https://otte...
[1]
[https://www.notion.so/enoemos/https-stackoverflow-com-questi...
He also wrote the other question that he links to, How to index a database column, with the request to get answers for each major type of database. So he's asking not so much to learn the answer but to provide a place for others to provide a catalog of answers.
This is different of course from the case where someone asks a genuine question then comes back and writes an answer to themselves when they have learned it. This happens a lot too.
Here's the lecture on tree indexes: https://www.youtube.com/watch?v=JHZFc4hMGhk
Yep, that old :(
And I've been thinking that I don't use the subject indexes on the online catalog anywhere near enough. They can surface things that the standard keyword search might miss or bury among irrelevant results.
Additionally, parent’s answer doesn’t actually answer the question, by saying what an index is, but the question was “how does it work?” The top SO answer does a great job with this one, I think. Another one a few answer down also goes into some of the downsides (it slows down writes, for one). The whole page is worth a skim if you’re not a DBA but have to fiddle with DBs on occasion.
1. Binary search. It's be really handy to have the URLs stored in a different order, maybe grouped by client_id first and then all the URLs for the same client are alphabetical. The index conceptually just contains the same rows in a different order.
2. The read vs write trade-off. Your data fits in memory if there's less than 10 TB of it (possibly up to 100 TB) so the big thing is latency, what an index does is, it requires you to write the same information twice in order to read it exponentially faster, so depending on how often do you write versus how often you read, indexes make less or more sense.
3. High fan-out trees. Once you have explained that the index is just an the same data in a different order, you have inserted a sort of ticking time bomb of misunderstanding. The problem is, a beginner programmer’s notion of a freely indexable list, such that binary search works on it, is an array. How do we insert into an array? With all the work of array copies! So you get people who think that random ID columns should never be indexed, because every write into the middle of the array has to shove half the data one cell to the right—unacceptable! So it really helps to say, “now we can store this as a binary tree, make one comparison per level of the tree.” Pause for understanding that the “list,” can be stored with such a tree. “but, modern computers have a nice property that right after accessing some memory the memory near that location is loaded into a cache... this makes arrays real fast. Suppose we don't just have the binary tree thing of 2 child nodes each representing 50% of our data, but an array with 100 pointers each representing 1% of the data, you get something like a 6x memory speedup from the cache, because your tree is one sixth the depth of the binary tree. And that's basically what a B-tree is, you use a higher fan-out of your sort tree to exploit the cache.”