Data Storage and Indexing
Data Storage and Indexing
The cost per unit of data as well as the speed of accessing data
decreases while moving down in the memory hierarchy. The storage
media at the top such as cache and main memory is the highest speed
memory and is referred to as primary storage. The storage media in the
next level consists of slower devices, such as magnetic disk, and is
referred to as secondary storage. The storage media in the lowest level
is the slowest storage devices, such as optical disk and magnetic tape,
and are referred to as tertiary storage. Let us discuss these storage
devices in detail.
Primary Storage
Primary storage generally offers limited storage capacity due to its high
cost but provides very fast access to data. Primary storage is usually
made up of semiconductor chips. Semiconductor memory may be
volatile or non-volatile in nature. The two basic forms of semiconductor
memory are static RAM or SRAM (used for cache memory) and dynamic
RAM or DRAM (used for main memory).
Secondary Storage
A disk contains one read-write head for each surface of a platter, which
is used to store and retrieve data from the surface of platter. Information
is magnetically stored on a sector by the read-write head. The head
moves across the surface of platter to access different tracks. All the
heads are attached to a single assembly called a disk arm. Thus, all the
heads of different platters move together. The disk platters mounted on a
spindle together with the heads mounted on a disk arm is known as
head-disk assemblies. All the read-write heads are on the equal
diameter track on different platters at one time. The tracks of equal
diameter on different platters form a cylinder. Accessing data of one
cylinder is much faster than accessing data that is distributed among
different cylinders. A close look at the internal structure of magnetic disk
is shown in Figure 7.2.
Learn More
Some disks have one read-write head for each track of platter. These
disks are termed as fixed-head disks, since one head is fixed on each
track and is not moveable. On the other hand, disks in which the head
moves along the platter surface are termed as moveable-head disks.
1. Seek: As soon as the disk unit receives the read/write command, the
read/write heads are positioned on specific track on the disk platter.
The time taken in doing so is known as seek time. It is average time
required to move the heads from one track to some other desired
track on the disk. Seek times of modern disk may range between 6–
15 milliseconds.
2. Rotate: Once the heads are positioned on the desired track, the
head of the specific platter is activated. Since the disk is rotated
constantly, the head has to wait for the required sector or cluster
(desired data) to come under it. This delay is known as rotational
delay time or latency of the disk. The average rotational latencies
range from 4.2 to 6.7 ms.
3. Data transfer: After waiting for the desired data location, the
read/write head transfers the data to or from the disk to primary
memory. The rate at which the data is read from or written to the
disk is known as data transfer rate. It is measured in kilobits per
second (kbps). Some of the latest hard disks have a data transfer
rate of 66 MB/second. The data transfer rate depends upon the
rotational speed of the disk. If the disk has a rotational speed of
6000 rpm (rotations per minute), having 125 sectors and 512
bytes/sector, the data transfer rate per revolution will be 125 × 512 =
64000 bytes. Hence, the total transfer rate per second will be
64000 × 6000/60 = 6,400,000 bytes/ second or 6.4 MB/second.
The combined time (seek time, latency time, and data transfer time) is
known as the access time. Specifically, it can be described as the period
of time that elapses between a request for information from disk or
memory, and the information arriving at the requesting device. Memory
access time refers to the time it takes to transfer a character from
memory to or from the processor, while disk access time refers to the
time it takes to place the read/write heads over the given sector and
transfer the data to or from the requested device. RAM may have an
access time of 80 nanoseconds or less, while disk access time could be
12–19 milliseconds.
Learn More
In the simplest form, data striping splits each byte of data into bits and
stores them across different disks. This splitting of each byte into bits is
known as bit-level data striping. Having 8-bits per byte, an array of
eight disks (or either a factor or multiple of eight) is treated as one large
logical disk. In general, bit i of each byte is written ith disk. However, if
an array of only two disks is used, all odd numbered bits go to first disk
and even numbered bits to second disk. Since each I/O request is
accomplished with the use of all disks in the array, transfer rate of I/O
requests goes to N times, where N represents the number of disks in the
array.
RAID level 0: RAID level 0 uses block-level data striping but does
not maintain any redundant information. Thus, the write operation
has the best performance with level 0, as only one copy of data is
maintained and no redundant information needs to be updated.
However, RAID level 0 does not have the best read performance
among all the RAID levels, since systems with redundant information
can schedule disk access based on shortest expected seek time and
rotational delay. In addition, RAID level 0 is not fault-tolerant because
failure of just one drive will result in loss of data. However, absence
of redundant information ensures 100 per cent space utilization for
RAID level 0 systems.
RAID level 1: RAID level 1 is the most expensive system as this level
maintains duplicate or redundant copy of data using mirroring. Thus,
two identical copies of the data are maintained on two different
disks. Every write operation needs to update both the disks, thus,
the performance of RAID level 1 system degrades while writing.
However, performance while read operation is improved by
scheduling request to the disk with the shortest expected access
time and rotational delay. With two identical copies of data, RAID
level 1 system ensures only 50 per cent space utilization.
RAID level 2: RAID level 2 is known as error-correcting code (ECC)
organization. Two most popular error detecting and correcting codes
are parity bits and hamming codes. In memory system, each byte is
associated with a parity bit. The parity bit is set to 0 if the number of
bits in the byte that are set to 1 is even; otherwise the parity bit is set
to 1. If any one bit in the byte gets changed, then parity of that byte
will not match with the stored parity bit. In this way, use of parity bit
detects all 1-bit errors in the memory system. Hamming code has
the ability to detect the damaged bit. It stores two or more extra bits
to find the damaged bit and by complementing the value of
damaged bit, the original data can be recovered. RAID level 2
requires three redundant disks to store error detecting and
correcting information for four original disks. Thus, effective space
utilization is about 57 per cent in this case. However, space
utilization increases with the number of data disks because check
disks grow logarithmically with the number of data disks.
RAID level 3: As discussed, RAID level 2 uses check disks to hold
information to detect the failed disk. However, disk controllers can
easily detect the failed disk and hence, check disks need not to
contain information to detect the failed disk. RAID level 3 maintains
only single check disk with parity bit information for error correction
as well as for detection. This level is also named as bit-interleaved
parity organization.
Performance of RAID level 2 and RAID level 3 are very similar but
RAID level 3 has lowest possible overheads for reliability. So, in
practice, level 2 is not used. In addition, level 3 has two benefits over
level 1. Level 1 maintains one mirror disk for every disk, whereas level
3 requires only one parity disk for multiple disks, thus, increasing
effective space utilization. In addition, level 3 distributes the data
over multiple disks, with N-way striping of data, which makes the
transfer rate for reading or writing a single block by N times faster
than level 1. Since every disk has to participate in every I/O
operation, RAID level 3 supports lower number of I/O operations per
second than RAID level 1.
NAS provides both storage and file system. It is often contrasted with
SAN, which provides only block-based storage and leaves file system
concern on the client side. The file based protocols used by NAS are NFS
or SMB, whereas SAN protocols are SCSI or fibre channel. NAS increases
the performance as the file serving is done by the NAS and not by the
server, which is responsible for doing other processing. The performance
of NAS devices depends heavily on the speed of and traffic on the
network, and also on the amount of cache memory on the NAS devices.
In addition to the buffer pool, the buffer manager maintains two variables
for each frame in the buffer pool.
Initially, the value of pin_count is set to 0 and dirty bit is turned off for
every frame. On receiving a request for a page, the buffer manager first
searches the buffer pool for that page. If the requested page is available
in any frame, its pin_count is incremented by one. If no frame in the
buffer pool is holding the requested page, buffer manager chooses a
frame for replacement using replacement policy. If the dirty bit is on for
the replacement frame, the page in that frame is written back to the disk
and then, the requested page is transferred from disk to that frame in the
buffer pool. After having the requested page in buffer pool, buffer
manager passes the memory address of frame that contains the
requested page to its requestor.
For each new page from disk, buffer manager always choose a frame
with pin_count 0 to be replaced, if no free frame is available. In case two
or more such frames are found, then buffer manager chooses a frame
according to its replacement policy.
Learn More
There are two approaches to organize the database in the form of files. In
the first approach, all the records of a file are of fixed-length. However, in
the second approach, the records of a file vary in size. A file of fixed-
length records is simple to implement as all the records are of fixed-
length. However, deletion of record results in fragmented memory. On the
other hand, in case of files of variable-length records, memory space is
efficiently utilized; however, locating the start and end of record is not
simple.
create PUBLISHER as
(P_ID char(5) PRIMARY KEY NOT NULL,
Pname char(20) NOT NULL,
Address char(50),
State char(20),
Phone numeric(10),
Email_id char(50))
It is clear from the given definition that each record consists of P_ID,
Pname, Address, State, Phone, and Email_id fields, resulting in records of
fixed-length, but of varying length fields. Assume that each character
requires 1 byte and numeric(10) requires 5 bytes, then a PUBLISHER record
is 150 bytes long. Figure 7.5 represents a record of PUBLISHER relation
with starting of each field within the record.
Sometimes there may be possibility that the values for a large number of
fields are not available or are null. In that case, we can store the
sequence of pair <field name, field value> instead of just field values
in each record (see Figure 7.10). In this figure, three separator characters
are used—one for separating two fields, second one for separating field
value from field name, and third one for separating two records.
After discussing how the database is mapped to files, we will discuss how
these file records can be mapped on to disk blocks. There are two ways
to organize or place them on to disk blocks. Generally, multiple records
are stored in one disk block; however, some files may have large records
that cannot fit in one block. Block size is not always multiple of record
size, therefore, each disk block might have some unused space. This
unused space can be utilized by storing part of a record on one block and
the rest on another. In case, consecutive blocks are not allocated to the
file, pointer at the end of first block points to the block that contains the
remaining part of its last record [see Figure 7.11(a)].
Such type of organization in which records can span more than one disk
block is called spanned organization. Spanned organization can be
used with variable-length records as well as with fixed-length records.
On the other hand, in unspanned organization the records are not
allowed to cross block boundaries, thus, part of each block is wasted
[see Figure 7.11(b)]. Unspanned organization is generally used with fixed-
length records. This organization ensures starting of records at known
position within the block, which makes processing of records simple. It is
advantageous to use spanned organization to reduce the lost space in
each block if average record is larger than a block.
Learn More
NOTE Generally records are stored contiguously in the disk block that
means next record starts where the previous record ends.
In a slotted page structure starting from the end of the block, the actual
records are stored contiuously and the free space is contiguous between
the final entry in the header array and the first record. The space for new
record is allocated at the end of free space and corresponding entry of
record location and record size is included in the header. Record is
deleted by removing its entry from the header and freeing the space
occupied by the record. To make the free space contiguous within the
block again, all the records before deleted records are shifted to their
right. In addition, header entry pointing to the end of free space is
updated as well.
Operations that can be carried out on a heap file include creation and
deletion of files, insertion and deletion of record, searching a particular
record, and scanning of all records in the file. Heap file supports efficient
insertion of new record; however, scanning, searching, and deletion of
records is an expensive process.
Generally, new record is appended at the end of file. The last page of file
is copied to the buffer, new record is added and then the page is written
back to the disk. The address of last page of file is kept in the file header.
Scanning requires retrieving all the pages of heap file and processing
each record on the page one after the other. Let a file has R records on
each page and every record takes S time to process. Further, if the file
contains P pages and retrieving one page requires T time, then total cost
to scan the complete file is P(T+RS).
For deleting a particular record, it needs to be located in the file using its
record-id. Record-id helps in identifying the page that contains the
record. The page is then transferred in the buffer and after having
located the record it is removed from the page and the updated page is
written back.
When a new record is to be inserted in the file, the page with enough free
space is located and the record is inserted in that page. If there is no
page with enough space to accommodate that new record, a new page is
allocated to the file and record is inserted in the new page.
NOTE Sequential file does not make any improvement in processing the
records in random order.
Things to Remember
Cut key hashing: This hash function ‘cuts’ some digits from the
hash field value (or simply key) and uses it as hash address. For
example, if there are 100 locations in the array, a 2-digit address, say
37, may be obtained from the key 1324 37 by picking the highlighted
digits. It is not a good algorithm because most of the key is ignored
and only a part of the key is used to compute the address.
Folded key: This hash function involves applying some arithmetic
functions, such as addition/ subtraction or some logical functions,
such as and/or to the key value. The result obtained is used as the
record address. For example, the key is broken down into a group of
2-digit numbers from the left most digits and they are added like 13
+ 24 + 37 = 74. The sum is then used as record address. It is better
than cut key hashing as the entire key is used but not good enough
as records are not distributed evenly among pages.
Division-remainder hashing: This hash function is commonly used
and in this the value of hash field is divided by N and remainder is
used as record address. Record address = (Key value) mod (N).
This technique works very well provided that N is either a prime number
or does not have a small divisor.
The main problem associated with most hashing functions is that they do
not yield distinct addresses for distinct hash field values, because the
number of possible values a hash field can take is much larger than the
number of available addresses to store records. Thus, sometimes a
problem, called collision, occurs when hash field value of a record to be
inserted hashes to an address which is already being occupied by
another record. It should be resolved by finding some other location to
place the new record. This process of finding another location is called
collision resolution. Some popular methods for collision resolution are
given here.
All these methods work well; however, each of them requires its own
algorithms for insertion, retrieval, and deletion of records. All the
algorithms for chained overflow are simple, whereas open addressing
requires tricky algorithm for deletion of records.
A good hash function must distribute records uniformly over the available
addresses so as to minimize collisions. In addition, it should always return
same value for same input. Generally, hashing works best when division
remainder hash function is used in which N is chosen as a prime number,
as it distributes the records better over the available addresses.
Static Hashing
The hashing scheme in which a fixed number of buckets, say N, are
allocated to a file to store records is called static hashing. The pages of
a file can be viewed as a collection of buckets, with one primary page
and additional overflow pages. The file consists of 0 to N–1 buckets, with
one primary page per bucket initially. Further, let V denote the set of all
values hash field can take then the hash function h maps V to N.
To search a record, the hash function transforms the hash field value to
the bucket to which the required record belongs. Hash field value of all
the records in the bucket is then verified to search the required record.
Note that to speed up the searching process within the bucket, all the
records are maintained in a sorted order by hash field value.
Figure 7.16 illustrates the static hashing which represents the records of
BOOK relation with Price as hash field. In this example, the hash function h
takes the remainder of Price after dividing it by three to determine the
bucket for a record. Function h is defined as
In static hashing, since the number of buckets allocated to a file are fixed
when the file is created, the primary pages can be stored on consecutive
disk pages. Hence, searching a record requires just one disk I/O, and
other operations, like insertion and deletion, require two I/Os (read and
write the page). However, as the file grows, long overflow chains are
developed which degrade the performance of the file as searching a
bucket requires searching all the pages in its overflow chain.
It is undesirable to use static hashing with files that grow or shrink a lot
dynamically, since number of buckets is fixed in advance. It is a major
drawback for dynamic files. Suppose a file grows substantially more than
the allocated space, a long overflow chain is developed which results in
poor performance. Similarly, if a file shrinks greatly, a lot of space is left
unused. In either case, the number of buckets allocated to the file needs
to be changed dynamically and new hash function based on new value of
N should be used for distribution of records. However, such
reorganization consumes a lot of time for large files. Another alternative
is to use dynamic hashing, which allows number of buckets to vary
dynamically with only minor (internal) reorganization.
Dynamic Hashing
In this technique, the hash function is applied on the hash field value and
the last d bits of hash value are used to locate the directory element. The
pointer in this array position points to the bucket to which the
corresponding record belongs. To understand this technique, consider a
directory consisting of an array of 22 size (see Figure 7.17), which means
an array of size 4. Here d is 2, thus, last 2 bits of hash value are used to
locate a directory element. Further, assume that each bucket can hold
three records. The search for a key, say 21, proceeds as follows. Last 2
bits of hash value 21 (binary 10101) hashes into the directory element 01,
which points to bucket 2.
Fig. 7.17 Extendible hashed file
Consider the insertion of a new record with hash field value 9 (binary
1001). It hashes to the directory element 01, which further points to the
bucket 2. Since bucket 2 has space for a new record, it is inserted there.
Next, consider the insertion of a record with hash field value 24 (binary
11000). It hashes to the directory element 00 which points to bucket 1,
which is already full. In this situation, extendible hashing splits this full
bucket by allocating a new bucket and redistributes the records across
the old bucket and its split image. To redistribute the records among
these two buckets, the last three bits of hash value are considered. The
last two bits (00 in this case) indicate the directory element and the third
bit differentiate between these two buckets. Splitting of bucket with
redistributing of records is shown in Figure 7.18. Now, the contents of
bucket 1 and bucket 1a are identified by 3 bits of hash value, whereas the
contents of all other buckets can be identified by 2 bits. To identify the
number of bits on which the bucket contents are based, a local depth is
maintained with each bucket, which specifies the number of bits required
to identify its contents.
Fig. 7.18 Extendible hashing with splitting bucket
Note that if the local depth of overflowed bucket is equal to the global
depth there is a need to double the number of entries in the directory and
global depth is incremented by one. However, if local depth of overflowed
bucket is less than the global depth there is no need to double the
directory entries. For example, consider the insertion of a record with
hash value 5 (binary 101). It hashes to the directory element 01 which
points to bucket 2, which is already full. This situation is handled by
splitting the bucket 2 and using the directory element 001 and 101 to
point to the bucket 2 and its split image, respectively, (see Figure 7.19).
Fig. 7.19 After inserting record with hash value 5
To delete a record, first the record is located and then removed from the
bucket. In case, the deletion leaves the bucket empty the bucket can be
merged with its split bucket image. The local depth is decreased if the
buckets are merged. After merging, if the local depth of all the buckets
becomes less than the global depth, the number of entries in the
directory can be halved and global depth is be reduced by one.
The main advantage of extendible hashing over static hashing is that the
performance of the file does not degrade as the file grows dynamically. In
addition, there is no space allocated in advance for future growth of the
file. However, buckets can be allocated dynamically as needed. The size
of directory is likely to be much smaller than the file itself, since each
directory element is just a page-id. Thus, the space overhead for the
directory table is negligible. The directory can be extended up to 2n,
where n is the number of bits in the hash value. Another advantage of
extendible hashing is that bucket splitting requires minor reorganization
in most cases. The reorganization is expensive when directory needs to
be doubled or halved. One disadvantage of extendible hashing is that the
directory must be accessed and searched before accessing the record in
the bucket. Thus, most record retrievals require two block accesses, one
for the directory and the other for the bucket.
Linear Hashing Linear hashing also allows a hash file to grow or shrink
dynamically by allocating new buckets. In addition, there is no need to
maintain a directory of pointers to buckets. Like static hashing, collision
can be handled by maintaining overflow chains of pages; however, linear
hashing solves the problem of long overflow chains. In linear hashing,
overflow of any bucket in the file leads to a bucket split. Note that the
bucket to be split is not necessarily the same as the overflow bucket,
instead buckets are chosen to be split in the linear order 0, 1, 2, ….
A key property of hash function hi+1 is that any record that is hashed to
bucket j by hi will hash either to bucket j or bucket T + j. The range of
hash function hi+1 is twice as that of hi, that is, if hi hashes a record into
one of T buckets, hi+1 hash that record in one of 2T buckets.
In order to search a record with hash key value V, first the hash function
hi is applied to V and if hi (V) < j, it means that the hashed bucket is
already split. Then, the hash function hi+1 is applied to V to determine
which of the two split buckets contain the record.
Since j is incremented with each split, so, when j = T, it indicates that all
the original buckets have been split. At this point, j is reset to 0 and any
overflow leads to the use of new hash function hi+2, denoted by hi+2 (V)
= V mod 4T. In general, linear hashing scheme uses a family of hash
functions hi+k (V) = V mod (2kT), where k = 0, 1, 2, …. Each time when
all the original buckets 0 through (2kT) - 1 have been split, k is
incremented by 1 and new hashing function hi+k is needed.
7.7 INDEXING
Once the records of a file are placed on the disk using some file
organization method, the main issue is to provide quick response to
different queries. For this, additional structure called index on the file can
be created. Creating an index on a file does not affect the physical
placement of the records but still provides efficient access to the file
records. Index can be created on any field of the file, and that field is
called indexing field or indexing attribute. Further, more than one index
can be created on a file.
Indexes can be created on the field based on which the file is ordered as
well as on the field based on which the file is not ordered. Consider an
index created on the ordered attribute ISBN of the BOOK relation (see
Figure 7.20). This index is called primary index, since it is created on the
primary key of the relation.
Fig. 7.20 Index on the attribute ISBN of BOOK relation
This index file contains two attributes—first attribute stores the value of
the attribute on which the index is created and second attribute contains
a pointer to the record in the original file. Note that it contains an entry for
the first record in each disk block instead of every value of the indexing
attribute. Such types of indexes which do not include an entry for each
value of the indexing attribute are called sparse indexes (or non-dense
indexes). On the other hand, the indexes which include an entry for each
value of the indexing attribute are called dense indexes.
Given the search-key value for accessing any record using primary index,
we locate the largest value in the index file which is less than or equal to
the search-key value. The pointer corresponding to this value directs us
to the first record of the disk block in which the required record is placed
(if available). If the first record is not the required record, we sequentially
scan the entire disk block in order to find that record. Insertion and
deletion operation on the ordered file is handled in the same way as
discussed in the sequential file. Here; however, it may also require
modifying the pointers in several entries of the index file.
It is not always the case that index is created on the primary key attribute.
If an index is created on the ordered non-key attribute, then it is called
clustering index and that attribute is called clustering attribute. Figure
7.21 shows a clustering index created on the non-key attribute P_ID of the
BOOK relation.
Learn More
Though dense index provides faster access to the file records than
sparse index, having a sparse index with one entry per block is
advantageous in terms of disk space and maintenance overhead while
update operations. Moreover, once the disk block is identified and its
records are brought into the memory, scanning them is almost negligible.
This index contains an entry for each distinct value of the clustering
attribute and the corresponding pointer points to the first record with that
clustering attribute value. Other records with the same clustering
attribute value are stored sequentially after that record, since the file is
ordered on that attribute.
Inserting a new record in the file is easy if space is available in the block
in which it has to be placed. Otherwise, a new block is allocated to the file
and the new record is placed in that block. In addition, the pointer of the
block to which the record actually belongs is made to point to the new
block.
So far, we have discussed the case in which the index is created on the
ordered attribute of the file. Indexes can also be created on the non-
ordered attribute of the file. Such indexes are called secondary indexes.
The indexing attribute may be a candidate key or a non-key attribute with
duplicate values. In either case, secondary index must contain an entry
for each value of the indexing attribute. It means the secondary index
must be a dense index. This is because the file is not ordered on the
indexing attribute and if some of the values are stored in the index, it is
not possible to find a record whose entry does not exist in the index.
Figure 7.22 shows a secondary index created on the non-ordered
attribute Book_title of Book relation.
One solution to this problem is to view the index file, which we refer to as
the first or base level of a multilevel index, just as any other sequential
file and construct a primary index on the index file. This index to the first
level is called the second level of the multilevel index. In order to search
a record, we first apply binary search on the second level index to find
the largest value which is less than or equal to the search-key. The
pointer corresponding to this value points to the block of the first level
index that contains an entry for the searched record. This block of first
level index is searched to locate the largest value which is less than or
equal to the search-key. The pointer corresponding to this value directs
us to the block of file that contains the required record.
If second level index is too small to fit in main memory at once, fewer
blocks of index file needs to be accessed from disk to locate a particular
record. However, if the second level index file is too large to fit in main
memory at once, another level of index can be created. In fact, this
process of creating the index on index can be repeated until the size of
index becomes small enough to fit in main memory. This type of index
with multiple levels (two or more levels) of index is called multilevel
index. Figure 7.24 illustrates multilevel indexing.
Fig. 7.24
B-trees
All the values in a node should be in the sorted order, it means V1 < V2 <
··· < Vn–1 within each node of the tree. In addition, the node pointed to
by any tree pointer Pi should contain all the values larger than the value
Vi–1 and less than the value Vi. Another constraint that the B-tree must
satisfy is that it must be balanced; it means all the leaf nodes should be
at the same level. B-tree also ensures that each node, except root and
leaf nodes, should be at least half full, that means it should have at least
n/2 tree pointers.
The number of tree pointers in each node (called fan-out) identifies the
order of B-tree.
B+-trees
Each leaf node has n–1 values along with a data pointer for each value. If
the indexing attribute is the key attribute, the data pointer points either to
the record in the file or to the disk block containing the record with that
indexing attribute value. On the other hand, if the indexing attribute is not
the key attribute, the data pointer points to the bucket of pointers, each
of which points to the record in the file.
The leaf nodes and internal nodes of a B+-tree corresponds to the first
level and other levels of multilevel index, respectively.
Since data pointers are not included in the internal nodes of a B+-tree,
more entries can be fit into an internal node of a B+-tree than
corresponding B-tree. As a result, we have larger order for B+-tree than
B-tree for the same size of disk block. A typical B+-tree of order n=3 is
shown in Figure 7.28.
To understand the concept, consider this query: List all the books from
BOOK relation where Category = “Textbook” and P_ID = “P001”. This query
involves two non-key attributes, namely, Category and P_ID, thus,
multiple records may satisfy either condition. There are three possible
strategies to process this query, which are given here.
The main advantage of this method is that it can be applied for range
queries. In addition, it is extended to any number of attributes in the
search-key. Grid file method is good for multiple-key search. On the
other hand, the main disadvantage is that it represents space and
management overhead in terms of grid array because it requires frequent
reorganization of grid files with dynamic files.
SUMMARY
KEY TERMS
Storage devices
Volatile storage
Non-volatile storage
Primary storage
Cache memory
Main memory
Flash memory
Secondary storage
Tertiary storage
Optical disc
CD-ROM
DVD-ROM
Tape storage
Sequential access
Direct access
Magnetic disk
Platter
Single-sided disk
Double-sided disk
Tracks and sectors
Read/write head
Disk arm
Spindle
Head-disk assemblies
Cylinder
Disk controller
SCSI, ATA, and SATA interfaces
Checksums
Seek time
Rotational delay
Data transfer time
Access time
Disk reliability and MTTF
RAID
Data striping
Bit-level data striping
Block-level data striping
Redundant information
Mirroring (or shadowing)
Mean time to failure
Mean time to repair
Error correcting codes and check disk
RAID levels
Storage area network (SAN)
Network-attached storage (NAS)
Pages
Buffer pool
Buffer manager
Frames
Pinning and unpinning pages
Page-replacement policies
Least recently used
Most recently used
Clock replacement
Fixed-length records
File header
Free list
Variable-length records
Mapping records
Spanned organization
Unspanned organization
Slotted page structure
File organization
Heap file organization
Heap file or pile file
Sequential file organization
Sequential file
Ordered field
Ordering key
Hash file organization
Hashing
Hash file or direct file
Hash function
Hash table
Cut key hashing
Folded key hashing
Division-remainder hashing
Collision
Collision resolution
Open addressing
Multiple addressing
Chained overflow
Bucket
Static hashing
Primary and overflow pages
Overflow chain of bucket
Dynamic hashing
Extendible hashing
Directory of pointers
Global depth
Local depth
Linear hashing
Indexing
Index
Indexing field or indexing attribute
Single-level index
Primary index
Sparse index
Dense index
Clustering index
Clustering attribute
Secondary index
Multilevel index
First or base level
Second level
B-tree
Tree pointers
Data pointers
B+-tree
Indexes on multiple keys
Composite search-key
Lexicographic order
Partitioned hashing
Grid files
EXERCISES
D. Practical Questions