By the end of this chapter you'll be able to…

  • 1Compute blocking factor and block count for spanned and unspanned organisation
  • 2Compare heap, sorted and hashed file organisations on search and insertion cost
  • 3Distinguish dense from sparse and primary from clustering from secondary indexes
  • 4Explain why a secondary index must be dense and why a primary index may be sparse
  • 5Compute the order of a B-tree from block, key, tree pointer and data pointer sizes
  • 6Compute the internal and leaf orders of a B-plus tree separately
  • 7Determine the number of levels needed for a given record count and the resulting query cost
  • 8Trace a B-plus tree insertion with a leaf split and explain the copy-up rule
  • 9Apply the extendible hashing split rule and say when the directory doubles
  • 10Quantify the write cost that each additional index imposes
💡
Why this chapter matters in GATE
An index trades space and write cost for a shorter search path, and every question in this area reduces to counting block accesses. GATE asks for blocking factors, B-tree and B-plus tree orders from block arithmetic, tree height for a given record count, and the extendible hashing directory-doubling rule.

Before you start — revise these

🔗
Disk blocks as the unit of transfer, and that a block access costs milliseconds
🔗
Logarithms base 2 and ceiling and floor arithmetic
🔗
Basic tree terminology: root, internal node, leaf, height

File Organization & Indexing

A database is stored in blocks on a disk, and a query's cost is essentially the number of blocks it reads.

The organising fact is that an index trades space and write cost for a shorter search path, and every question in this chapter reduces to counting the blocks a search must read.

A heap file reads them all. A sorted file reads a logarithmic number. A B-plus tree reads one per level plus one for the record. A hash file reads one, when it works.

The second organising fact is that the branching factor is set by arithmetic on the block size, and getting that arithmetic right is what most numerical questions actually test. A node holds as many pointers as fit in one block, and everything about tree height follows.

The third is that indexes are not free. Every insertion must update every index on the table, so a table with five indexes pays five times on writes to buy faster reads.

1. Records, Blocks and Blocking Factor

A disk transfers whole blocks, so the unit of cost is the block access, not the byte.

The blocking factor is how many records fit in a block, computed as the floor of block size divided by record size.

Spanned organisation lets a record cross a block boundary, avoiding waste but requiring a pointer to the continuation. Unspanned organisation does not, which is simpler and is what exam questions assume unless stated.

The number of blocks a file occupies is the ceiling of record count divided by blocking factor.

Three basic file organisations exist.

A heap file appends new records at the end. Insertion costs one block access; searching costs a full scan, averaging half the file for a successful search and all of it for an unsuccessful one.

A sorted file keeps records ordered on some field. Binary search finds a record in about block accesses for blocks, but insertion must maintain the order and is expensive.

A hash file computes the block address from a key, giving one access in the ideal case, but supports no range queries at all.

2. Kinds of Index

An index is an auxiliary structure mapping a search key to a record location, and three orthogonal distinctions matter.

A dense index has one entry per record. A sparse index has one entry per block, pointing at its first record.

A sparse index is smaller and therefore shallower, but it works only if the file is ordered on the index field, since finding a record requires scanning within the block the index points to.

A primary index is built on the ordering key field of an ordered file, and is sparse. There is at most one per file.

A clustering index is built on an ordering field that is not a key, so many records share a value.

A secondary index is built on any non-ordering field and must be dense, because the records with a given value are scattered and none can be found by scanning from a neighbour.

A secondary index on a non-key field needs an extra level of indirection, typically a bucket of record pointers per value, because the number of matching records varies.

A multilevel index treats the index itself as an ordered file and indexes it, repeating until the top level fits in one block. That is exactly what a B-plus tree automates.

3. B-Trees

A B-tree of order has at most children and at least the ceiling of , except the root, which needs only two.

All leaves are at the same level, which is what keeps the height logarithmic and the worst case equal to the average case.

A B-tree stores data pointers in every node, internal nodes included.

A node with pointers holds keys, and each key is accompanied by a data pointer.

The order is determined by the block size. With block size , key size , tree pointer size and data pointer size , the constraint is that must not exceed .

A search can terminate at any level, which sounds like an advantage but is a small one, since the great majority of keys live in the leaves regardless.

4. B-Plus Trees

A B-plus tree stores data pointers only in the leaves. Internal nodes hold keys purely for navigation.

This is the decisive difference. Removing the data pointers from internal nodes lets each hold more keys, which raises the branching factor and lowers the height.

Leaves are linked in a list, so a range query finds the first matching key through the tree and then walks the leaf chain sequentially, without revisiting the internal nodes.

Keys may appear twice, once as a separator in an internal node and once in a leaf, which is not redundancy but the price of navigation.

The internal node order satisfies .

The leaf order is different, because a leaf holds key and data pointer pairs plus one pointer to the next leaf: .

Computing these two separately is the most common source of lost marks, since candidates apply the internal formula to the leaves.

Every search costs exactly the height plus one, one access per level down to a leaf plus one for the record itself, which makes the cost uniform and predictable.

5. Insertion, Deletion and Height

Insertion places the key in the correct leaf. If the leaf overflows, it splits into two, and the middle key is copied up into the parent.

In a B-tree the middle key moves up; in a B-plus tree it is copied up, because the leaf must retain every key.

A split can cascade upward, and if the root splits, the tree grows a level. That is the only way a B-plus tree gains height, which is why growth is at the root rather than the leaves.

Deletion may cause underflow, repaired by borrowing a key from a sibling or merging with one. Merging can cascade and shrink the tree.

Height bounds follow from the fanout. A tree of height with minimum fanout holds at least about keys, and with maximum fanout holds at most about .

Because the fanout is in the hundreds, real B-plus trees are three or four levels deep even for very large tables, which means any record is four block accesses away.

6. Hashing

Static hashing fixes the number of buckets at creation. A good hash function distributes keys evenly, and each bucket is one block.

Overflow chains form when a bucket fills, and performance degrades as chains lengthen, which is unavoidable once the file grows past its design size.

Extendible hashing uses a directory of entries, where is the global depth, indexed by the first bits of the hash value.

Each bucket carries a local depth not exceeding , and directory entries point at it.

When a bucket overflows, it splits. If its local depth was less than the global depth, only the bucket splits and the directory is untouched. If they were equal, the directory doubles first.

Directory doubling is cheap because it copies pointers, not records, which is the whole point of the indirection.

Linear hashing avoids the directory entirely, splitting buckets in a fixed round-robin order regardless of which one overflowed, which trades some uniformity for the absence of a directory.

7. Worked Examples

Example 1. A file has 30,000 records of 100 bytes each. The block size is 1024 bytes and organisation is unspanned. Compute the blocking factor, the number of blocks, and the average block accesses for a successful linear search and for a binary search on a sorted file.

The blocking factor is the floor of , which is 10 records per block.

The wasted 24 bytes per block are the cost of unspanned organisation, about 2.3 percent here.

The number of blocks is the ceiling of , which is 3000.

A successful linear search reads on average half the file, so 1500 block accesses.

An unsuccessful linear search reads all 3000.

A binary search on a sorted file costs the ceiling of , which is 12 block accesses, since and .

The improvement is from 1500 to 12, which is the argument for ordering, and an index will improve it further.

Example 2. With a block size of 1024 bytes, a key of 9 bytes, a tree pointer of 6 bytes and a data pointer of 7 bytes, compute the order of a B-tree and both orders of a B-plus tree.

For the B-tree, a node with pointers holds keys, each with a data pointer.

The constraint is , that is .

So , giving , hence .

For the B-plus tree internal node, there is no data pointer.

The constraint is , that is .

So , giving , hence .

For the B-plus tree leaf, each entry is a key and a data pointer, plus one pointer to the next leaf.

The constraint is , that is .

So , hence .

Note the gain from removing data pointers: 68 against 47, a branching factor about 45 percent higher, which is why B-plus trees are used and B-trees are not.

Example 3. A B-plus tree has internal order 68 and leaf order 63, holding one million records. How many levels does it need, and how many block accesses does a point query cost?

Work from the leaves upward.

Leaves hold at most 63 entries each, so one million records need at least the ceiling of , which is 15,874 leaves.

The level above holds at most 68 pointers per node, so it needs at least the ceiling of , which is 234 nodes.

The next level up needs the ceiling of , which is 4 nodes.

The next needs 1 node, which is the root.

So the tree has 4 levels: root, two internal levels, and the leaf level.

A point query reads one block per level, which is 4, plus one block for the record itself, giving 5 block accesses.

Compare with the sorted file's 12 and the heap file's 1500.

Note also how slowly this grows. Multiplying the record count by 68 adds exactly one level, so a 68-million-record table needs 5 levels, and 6 accesses. That flatness is why B-plus trees dominate.

Example 4. Insert keys 10, 20, 30, 40 into an initially empty B-plus tree with internal order 3 and leaf order 3, showing each split.

Order 3 means an internal node holds at most 3 pointers and 2 keys, and a leaf holds at most 3 keys.

Insert 10, 20, 30. All fit in the single leaf, which is also the root. The tree is one node holding 10, 20, 30.

Insert 40. The leaf would need 4 keys, which overflows.

Split the leaf. With 4 keys, the split puts 10 and 20 in the left leaf and 30 and 40 in the right leaf.

Copy the first key of the right leaf, which is 30, up into a new root.

The result is a root holding the single key 30, with a left child holding 10 and 20, and a right child holding 30 and 40.

Note that 30 appears twice, once as a separator in the root and once as data in the leaf. This is the defining behaviour of a B-plus tree.

Contrast with a B-tree. There, 30 would move up rather than being copied, appearing only in the root, and the right child would hold only 40. The leaves would no longer contain every key.

The two leaves are linked, so a range query for keys above 15 finds the left leaf, reads 20, and follows the link to read 30 and 40 without touching the root again.

Example 5. An extendible hash index has global depth 2 and four buckets, one per directory entry, each with local depth 2. Bucket 00 overflows. Describe what happens, then describe the different outcome if its local depth had been 1.

Case one: local depth equals global depth, both 2.

Only one directory entry points at this bucket, so splitting it would leave nowhere to record the distinction.

The directory must double first, becoming 8 entries indexed by 3 bits, and the global depth becomes 3.

Every existing bucket is now pointed at by two entries, and their local depths stay at 2, unchanged.

Now split bucket 00 into buckets for 000 and 100, both with local depth 3, redistributing its records by their third hash bit.

No records outside that bucket move, which is the property that makes extendible hashing worthwhile.

Case two: local depth 1, global depth 2.

Two directory entries point at this bucket, since .

There is already spare directory capacity to distinguish the halves, so no doubling is needed.

Split the bucket into two, each with local depth 2, and repoint one of the two directory entries at the new bucket.

The directory size and global depth are unchanged.

The rule to remember: double the directory only when the splitting bucket's local depth equals the global depth.

Example 6. A table has 500,000 records and five secondary indexes. Compare the cost of a point query and of an insertion, and state the design consequence.

A point query using one index costs the index's height plus one for the record. With a fanout in the hundreds, that is about 4 accesses.

Without any index the same query costs a full scan. At 10 records per block that is 50,000 block accesses.

So each index buys a factor of over ten thousand on the queries it serves.

Now consider an insertion.

Writing the record itself costs one block access, or two counting the read.

But every one of the five indexes must be updated, because each must now contain an entry for the new record.

Each index update costs a traversal plus a write, so about 5 accesses each, giving 25 for the five, and more if any node splits.

The insertion therefore costs roughly 27 accesses instead of 2, a factor of thirteen.

The design consequence is that indexes should be chosen against the actual query mix. An index that serves no query is pure cost, and on a write-heavy table the total index count is a direct throughput constraint.

This is also why bulk loading drops indexes first and rebuilds them afterwards, since building an index once over sorted data is far cheaper than maintaining it through half a million individual insertions.

Summary

An index trades space and write cost for a shorter search path, and every question here counts block accesses.

Blocking factor is the floor of block size over record size, and block count is the ceiling of records over blocking factor. Heap files scan, sorted files binary search in about , hash files reach a record in one access but support no ranges.

A dense index has an entry per record and a sparse index one per block. Primary indexes are sparse on the ordering key; clustering indexes sit on a non-key ordering field; secondary indexes must be dense, and on a non-key field need a bucket of pointers.

A B-tree stores data pointers in every node and satisfies . A B-plus tree stores them only in leaves, so internal nodes satisfy and leaves satisfy . Computing the two B-plus orders separately is essential.

Removing data pointers from internal nodes raises the branching factor substantially, which is why B-plus trees won. Linked leaves make range queries sequential.

A leaf split copies the middle key up in a B-plus tree and moves it up in a B-tree. The tree gains height only when the root splits.

Real trees are three or four levels deep, so a point query is four or five block accesses regardless of table size, and multiplying the row count by the fanout adds exactly one level.

Extendible hashing indexes a directory of entries by the first hash bits, and doubles the directory only when the splitting bucket's local depth equals the global depth. Linear hashing avoids the directory by splitting in a fixed order.

Every index must be updated on every insertion, so an index that serves no query is pure cost, and bulk loads drop and rebuild rather than maintain. Choosing indexes is therefore a decision about the query mix, not a decision that can be made from the schema alone.

Key formulas & results

Everything to memorise for the exam hall, in one card. Screenshot this for revision.

The organising principle
an index trades space and write cost for a shorter search path
Every cost question here is a count of block accesses, and every index must be paid for on every insertion.
Blocking factor
bfr = floor(block size divided by record size), unspanned
The remainder is wasted per block. Spanned organisation avoids the waste but needs a continuation pointer.
Block count
blocks = ceiling(number of records divided by blocking factor)
The basis of every scan cost. A linear search averages half this for a success and all of it for a failure.
B-tree order
p times P plus (p minus 1) times (K plus Pr) is at most B
Data pointers sit in every node, which is why the B-tree order is markedly lower than the B-plus tree internal order.
B-plus tree internal order
p times P plus (p minus 1) times K is at most B
No data pointers in internal nodes, so more keys fit and the tree is shallower.
B-plus tree leaf order
p_leaf times (K plus Pr) plus P is at most B
A leaf holds key and data pointer pairs plus one pointer to the next leaf. Computing this separately from the internal order is essential.
Point query cost
block accesses = number of levels plus one for the record
Uniform for every key, because all leaves are at the same level.
Height growth
multiplying the record count by the fanout adds exactly one level
With fanout in the hundreds, real trees stay three or four levels deep for any realistic table size.
B-plus split rule
copy the middle key up in a B-plus tree; move it up in a B-tree
The leaf must retain every key in a B-plus tree, so a separator appearing twice is expected, not redundant.
Extendible hashing split rule
double the directory only when the splitting bucket's local depth equals the global depth
A bucket with local depth below the global depth has spare directory entries and splits without doubling. Doubling copies pointers, not records.
Directory sharing
a bucket with local depth d prime is pointed at by 2 to the power (d minus d prime) directory entries
This is what tells you whether a split needs a doubling.
⚠️

Traps GATE sets — and how to dodge them

These are the exact option-traps and misreads that cost marks under negative marking.

WATCH OUT
Using the internal node formula for B-plus tree leaves
Leaves carry a data pointer with every key and one extra pointer to the next leaf, so the arithmetic is genuinely different. Compute both orders.
Why it happens: Both are nodes of the same tree, so one formula seems to cover both.
WATCH OUT
Including a data pointer in the B-plus tree internal node calculation
The whole point of a B-plus tree is that internal nodes carry only keys and tree pointers. Including data pointers gives the B-tree answer instead.
Why it happens: The B-tree formula is learned first and is applied by habit.
WATCH OUT
Rounding the order up instead of down
The node must fit inside one block, so take the floor. Rounding up gives a node that does not fit.
Why it happens: The inequality produces a fractional bound and rounding up feels like the safer direction.
WATCH OUT
Forgetting the final access to the record itself
A point query costs one access per level plus one for the data block, so a four-level tree costs five accesses.
Why it happens: Attention goes to the tree traversal, which is the interesting part of the question.
WATCH OUT
Claiming a secondary index can be sparse
A sparse index requires the file to be ordered on that field, so that a scan from the pointed-to record finds the target. A secondary index has no such ordering and must be dense.
Why it happens: Sparse indexes are smaller, so they seem preferable wherever they are allowed.
WATCH OUT
Doubling the extendible hashing directory on every overflow
Doubling happens only when the splitting bucket's local depth equals the global depth. Otherwise there are already spare directory entries pointing at it.
Why it happens: The doubling is the memorable operation, so it is applied to every split.
WATCH OUT
Assuming a B-tree is faster than a B-plus tree because a search can end early
The overwhelming majority of keys live in leaves either way, and the B-plus tree's higher fanout reduces the height for every key. Range queries also favour the linked leaves decisively.
Why it happens: Terminating at an internal node genuinely saves accesses in that case.
WATCH OUT
Counting only read cost when comparing indexed and unindexed designs
Every index must be updated on every insertion. Five secondary indexes turn a two-access insert into roughly twenty-seven.
Why it happens: Indexes are introduced as a way to speed up queries, so writes are out of mind.

Exam-pattern practice

PYQ-style questions with full solutions. Work through them as a readiness check — mark yourself honestly and get your gap report at the end.

Readiness check

Are you exam-ready for File Organization & Indexing (B and B+ Trees)?

10 problems from this chapter. Try each one, reveal the worked solution, mark yourself honestly — get your gap report at the end.

10 questions~7 min

5-minute revision

The whole chapter, distilled. Read this the night before the exam.

  • Cost is measured in block accesses; an index buys reads and costs writes
  • Blocking factor is floor(block over record); block count is ceiling(records over bfr)
  • Heap: cheap insert, full scan. Sorted: log b search, costly insert. Hash: one access, no ranges
  • Dense index has an entry per record; sparse has one per block and needs the file ordered
  • Primary index is sparse on the ordering key; clustering sits on a non-key ordering field
  • Secondary index must be dense, and on a non-key field needs a bucket of pointers
  • B-tree: data pointers everywhere, order from pP + (p-1)(K + Pr) at most B
  • B-plus internal: pP + (p-1)K at most B; leaf: p_leaf(K + Pr) + P at most B
  • Always compute the two B-plus orders separately, and take the floor
  • Removing data pointers raises fanout substantially, which is why B-plus trees won
  • Leaves are linked, so range queries walk sequentially without revisiting internal nodes
  • A B-plus split copies the middle key up; a B-tree split moves it up
  • The tree gains height only when the root splits
  • Point query costs levels plus one; four-level trees are typical for very large tables
  • Extendible hashing: directory of 2 to the d entries, bucket with local depth d prime shared by 2 to the (d minus d prime) entries
  • Double the directory only when local depth equals global depth; doubling copies pointers, not records
  • Linear hashing splits in a fixed order and needs no directory
  • Five indexes turn a two-access insert into roughly twenty-seven

GATE question blueprint

How this topic is asked, tier by tier — so you can prep to the pattern.

Typical weightage: 6

Question styleMarks eachTypical countWhat it tests
B and B plus trees31
File organization11
Index types11
Hashing11

Exam-hall strategy

Battle-tested tips from mentors and toppers for this topic under the sectional clock.

  1. Write the node constraint as an inequality before substituting numbers, and state which pointers the node carries, since that is where the B-tree and B-plus tree answers diverge. Always take the floor of the resulting bound. For height questions, work from the leaves upward using ceilings at each level, and remember to add one access for the record itself unless the question says the tree is clustered. In insertion traces, state whether the middle key is copied or moved, because that single word distinguishes the two structures. For extendible hashing, compare local depth with global depth first, since that comparison decides everything else in the answer.

Beyond the exam

Where this skill shows up in the job you're competing for — and in life.

InnoDB stores every table as a B-plus tree keyed by its p…

InnoDB stores every table as a B-plus tree keyed by its primary key, so the row data lives in the leaves and a secondary index lookup costs a second traversal

PostgreSQL's default index is a B-tree in name but a B-pl…

PostgreSQL's default index is a B-tree in name but a B-plus tree in structure, and its EXPLAIN output shows exactly the level-plus-one cost model in this chapter

Key-value stores such as RocksDB and Cassandra use log-st…

Key-value stores such as RocksDB and Cassandra use log-structured merge trees instead, trading read amplification for sequential writes on flash

File systems reuse the same structure

File systems reuse the same structure, with ext4 directories and NTFS metadata both indexed by B-trees for the same block-access reasons

Index selection tooling in every major database recommend…

Index selection tooling in every major database recommends indexes by simulating the query mix, which is the read-versus-write trade-off in this chapter made automatic

Where else this topic is tested

Prepare once, score in every exam that asks it.

GATE CS
GATE DA
UGC NET Computer Science
ISRO Scientist SC
BARC Computer Science

Questions aspirants ask

Pulled from the Q&A community and mentor sessions.

Because the cost unit is a block access, not a comparison. A binary tree over a million keys is twenty levels deep and each level is a separate block read. A B-plus tree packs hundreds of keys into each block, so the same search touches four blocks. The tree is shaped by the disk, not by the comparison count.

Mostly yes for read-heavy workloads, since the block-oriented cost model still applies even without seek time. Write-heavy workloads increasingly use log-structured merge trees instead, because they turn random updates into sequential writes, which matters a great deal for flash endurance and write amplification.

A clustering index is built on an ordering field that is not a key, so several records share each index value. A clustered table, in vendor terminology, is one whose rows are physically stored in the leaves of its primary index, so there is no separate record fetch. The terms overlap confusingly and exam questions use the textbook sense.

No, because a primary index requires the file to be physically ordered on the index field, and a file has only one physical order. Every other index on the table must be secondary and therefore dense.

Because it confines the cost of growth. Without the indirection, adding capacity means rehashing every record; with it, a split touches exactly one bucket and, at worst, copies a directory of pointers. Linear hashing removes the directory by accepting that the bucket that splits is not the bucket that overflowed.

No. If a query matches a large fraction of the table, using a secondary index means one random access per matching record, which can easily cost more than a sequential scan of the whole file. Optimisers estimate selectivity precisely to make this decision, and they routinely choose the scan.
Header Logo