Then, traverses the branch blocks to find the first leaf block that contains relevant data. When it gets to a leaf block, it is the leaf block with the "lowest" value (assuming a normal ascending range scan, there are descending scans as well).
Then, we read the key values in sorted order - leaf block by leaf block (each leaf block is part of a doubly linked list - we can go to the next leaf without having to traverse the branch blocks again). We know when to stop when the key value we read is greater than our stop value.
EG: where x between 10 and 20;
root block read -> branch(es) read -> first leaf block with 10 on it. We keep reading values - reading another leaf block as needed - until we encounter a key that is greater than 20 or we hit the end of the leaf blocks. We know we are done.
An index range scan uses single block IO's because the blocks in the branches and leafs are not contiguous with respect to each other - they are scattered randomly throughout the tablespace.
We can either:
a) get the rowids and then go to the table
b) get A rowid, go to table, get NEXT rowid, go to table and so on
it depends, it depends on the plan and the nature of the query.