SQL Server Indexes

Download as docx, pdf, or txt
Download as docx, pdf, or txt
You are on page 1of 14

SQL Server Indexes

Index is a table that helps in faster query results and quick data retrieval from the database. Index tables use
indexing, a technique that uses data structures to optimize the searching time of a database query. Indexing
makes database performance better. It also consumes lesser space in the main memory.
What is an INDEX?

Index usually consists of two columns which are a key-value pair. The two columns of the index table (i.e., the
key-value pair) contain copies of selected columns of the tabular data of the database.

Generally, we store the selected Primary or Candidate keys in a sorted manner so that we can reduce the overall
query time or search time (from linear search to binary search).
Data Reference contains a set of pointers that holds the address of the disk block. The pointed disk block
contains the actual data referred to by the Search Key. Data Reference is also called Block Pointer because it
uses block-based addressing.
Indexing is used to quickly retrieve particular data from the database. Indexing reduces the number of disks
required to access a particular data by internally creating an index table. Indexing is achieved by creating Index-
table or Index.

Advantages of Creating Index Table or Indexing:


 Indexing helps in faster query results or quick data retrieval.
 Indexing helps in faster sorting and grouping of records
 Some Indexing uses sorted and unique keys, which helps to retrieve sorted queries even faster.
 Index tables are smaller in size, so they require lesser memory.
 As Index tables are smaller in size, they are stored in the main memory.
 Since CPU speed and secondary memory speed have a large difference, the CPU uses this main
memory index table to bridge the gap of speeds.
 Indexing helps in better CPU utilization and better performance.

How does Index Work?

Now that we know index and its advantages, let us now know how index works in SQL. Generally, the database
takes the column provided with the CREATE INDEX command and sorts the column values using a special
data structure called B-trees.

B-tree is a type of tree data structure that contains 2 things: Index Key and its corresponding disk address.
Index Key refers to a certain disk address, and that disk further contains rows or tuples of data. Using B-tree, we
can achieve fast searches and fast retrievals. Also, the disk space used is low.

Since the data structure, B_tree, is sorted in order, it makes our search more efficient. So, this is how the index
works in SQL. Now let us take a few examples to visualize how index works in SQL.

Example - We want to store the below three-column table in the database.

The B-tree representation will be like this:


How Does the Database Know What Other Fields in the Table to Return?
As we have discussed above, the index table has two columns. The first column stores the key that points (or
references) to a particular location of information. Using the student table example, we can visualize that a
certain roll number index will point to a record of the table. The record can contain numerous columns or
attributes. Hence, using an index, the database can know about the rest of the attributes of the table.

SQL Server provides two types of indexes:


 clustered index
 non-clustered index.
SQL Server Clustered Indexes
The production. parts table does not have a primary key; therefore, SQL Server stores its rows in an unordered
structure called a heap.
When you query data from the production.parts table, the query optimizer needs to scan the whole table to
locate the correct one.
For example, this statement finds the part whose part id is 5.
SELECT part_id, part_name
FROM production.parts
WHERE part_id = 5;

If you display the estimated execution plan in SQL Server Management Studio, you can see how SQL Server
came up with the following query plan:
Note that to display the estimated execution plan in SQL Server Management Studio, you click the following
button or select the query and press the keyboard shortcut Ctrl-L:

Because the production.parts table has just five rows, the query will execute very fast. However, if the table
contains a large number of rows, SQL Server will take a lot of time and resource to search for data.
To resolve this issue, SQL Server provides a dedicated structure to speed up retrieval of rows from a table
called index.
SQL Server has two types of indexes: clustered index and non-clustered index. We will focus on the clustered
index in this tutorial.
A clustered index stores data rows in a sorted structure based on its key values. Each table has only one
clustered index because data rows can be only sorted in one order. The table that has a clustered index called a
clustered table.
The following picture illustrates the structure of a clustered index:
A clustered index organizes data using a special structured so-called B-tree (or balanced tree) which enables
searches, inserts, updates and deletes in logarithmic amortized time.
In this structure, the top node of the B-tree is called the root node. The nodes at the bottom level are called
the leaf nodes. Any index levels between the root and the leaf nodes are known as intermediate levels.
In the B-Tree, the root node and intermediate level nodes contain index pages that hold index rows. The leaf
nodes contain the data pages of the underlying table. The pages in each level of the index are linked using
another structure called a doubly linked list.
SQL Server Clustered Index and Primary key constraint
When you create a table with a primary key, SQL Server automatically creates a corresponding clustered index
based on columns included in the primary key.
This statement creates a new table named production.part_prices with a primary key that includes two
columns: part_id and valid_from.
CREATE TABLE production.part_prices(
part_id int,
valid_from date,
price decimal(18,4) not null,
PRIMARY KEY (part_id, valid_from)
);

If you add a primary key constraint to an existing table that already has a clustered index, SQL Server will
enforce the primary key using a non-clustered index:
This statement defines a primary key for the production.parts table:
ALTER TABLE production.parts ADD PRIMARY KEY(part_id);
SQL Server created a non-clustered index for the primary key.
Using SQL Server CREATE CLUSTERED INDEX statement to create a clustered index.
In case a table does not have a primary key, which is very rare, you can use the CREATE CLUSTERED
INDEX statement to define a clustered index for the table.
The following statement creates a clustered index for the production.parts table:
CREATE CLUSTERED INDEX ix_parts_id ON production.parts (part_id);
If you open the Indexes node under the table name, you will see the new index name ix_parts_id with
type Clustered.

When executing the following statement, SQL Server traverses the index (Clustered index seek) to locate the
row, which is faster than scanning the whole table.
SELECT part_id, part_name
FROM production.parts
WHERE part_id = 5;

SQL Server CREATE CLUSTERED INDEX syntax


The syntax for creating a clustered index is as follows:
CREATE CLUSTERED INDEX index_name ON schema_name.table_name (column_list);
In this syntax:
 First, specify the name of the clustered index after the CREATE CLUSTERED INDEX clause.
 Second, specify the schema and table name on which you want to create the index.
 Third, list one or more columns included in the index.

SQL Server Non - Clustered Indexes


A nonclustered index is a data structure that improves the speed of data retrieval from tables. Unlike a clustered
index, a nonclustered index sorts and stores data separately from the data rows in the table. It is a copy of
selected columns of data from a table with the links to the associated table.
Similar to a clustered index, a nonclustered index uses the B-tree structure to organize its data.
A table may have one or more nonclustered indexes and each non-clustered index may include one or more
columns of the table.
The following picture illustrates the structure non-clustered index:

Besides storing the index key values, the leaf nodes also store row pointers to the data rows that contain the key
values. These row pointers known as row locators.
If the underlying table is a clustered table, the row pointer is the clustered index key. In case the underlying
table is a heap, the row pointer points to the row of the table.
SQL Server CREATE INDEX statement
To create a non-clustered index, you use the CREATE INDEX statement:
CREATE [NONCLUSTERED] INDEX index_name ON table_name(column_list);
In this syntax:
 First, specify the name of the index after the CREATE NONCLUSTERED INDEX clause. Note that
the NONCLUSTERED keyword is optional.
 Second, specify the table name on which you want to create the index and a list of columns of that table
as the index key columns.
SQL Server CREATE INDEX statement examples
We will use the sales.customers from the sample database for the demonstration.

The sales.customers table is a clustered table because it has a primary key customer_id.
A) Using the SQL Server CREATE INDEX statement to create a nonclustered index for one column
example
This statement finds customers who locate in Atwater:
SELECT customer_id, city
FROM sales.customers
WHERE city = 'Atwater';
If you display the estimated execution plan, you will see that the query optimizer scans the clustered index to
find the row. This is because the sales.customers table does not have an index for the city column.

To improve the speed of this query, you can create a new index named ix_customers_city for the city column:
CREATE INDEX ix_customers_city ON sales.customers(city);
Now, if you display the estimated execution plan of the above query again, you will find that the query
optimizer uses the nonclustered index ix_customers_city:
B) Using SQL Server CREATE INDEX statement to create a nonclustered index for multiple columns
example
The following statement finds the customer whose last name is Berg and first name is Monika:
SELECT customer_id, first_name, last_name
FROM sales.customers
WHERE last_name = 'Berg' AND first_name = 'Monika';

The query optimizer scans the clustered index to locate the customer.
To speed up the retrieval of data, you can create a nonclustered index that includes
both last_name and first_name columns:
CREATE INDEX ix_customers_name ON sales.customers(last_name, first_name);
Now, the query optimizer uses the index ix_customers_name to find the customer.
SELECT customer_id, first_name, last_name
FROM sales.customers
WHERE last_name = 'Berg' AND first_name = 'Monika';

When you create a nonclustered index that consists of multiple columns, the order of the columns in the index is
very important. You should place the columns that you often use to query data at the beginning of the column
list.
For example, the following statement finds customers whose last name is Albert. Because the last_name is the
leftmost column in the index, the query optimizer can leverage the index and uses the index seek method for
searching:
SELECT customer_id, first_name, last_name
FROM sales.customers
WHERE last_name = 'Albert';
This statement finds customers whose first name is Adam. It also leverages the ix_customer_name index. But it
needs to scan the whole index for searching, which is slower than index seek.
SELECT customer_id, first_name, last_name
FROM sales.customers
WHERE first_name = 'Adam';

Therefore, it is a best practice to place the columns that you often use to query data at the beginning of the
column list of the index.
Rename Index
Using the system stored procedure sp_rename
The sp_rename is a system-stored procedure that allows you to rename any user-created object in the current
database including table, index, and column.
The statement renames an index:
EXEC sp_rename index_name, new_index_name, N'INDEX';
Or you can use the explicit parameters:
EXEC sp_rename @objname = N'index_name', @newname = N'new_index_name', @objtype = N'INDEX';
For example, the following statement renames the index ix_customers_city of the sales.customers table
to ix_cust_city:
EXEC sp_rename
@objname = N'sales.customers.ix_customers_city',
@newname = N'ix_cust_city' ,
@objtype = N'INDEX';
Or in short:
EXEC sp_rename
N'sales.customers.ix_customers_city',
N'ix_cust_city' ,
N'INDEX';
Renaming an index using the SQL Server Management Studio (SSMS)
To change the name of an index to the new one using the SSMS, you follow these steps:
First, navigate to the database, table name, and indexes:
Second, right-click on the index, which you want to change the name and choose the rename menu item. In the
following picture, we will rename the index ix_customers_name of the sales.customers table:

Third, type the new name and press enter. The following picture shows the ix_customers_name index change
to ix_cust_fullname:
Disable Index
To disable an index, you use the ALTER INDEX statement as follows:
ALTER INDEX index_name ON table_name DISABLE;
To disable all indexes of a table, you use the following form of the ALTER INDEX statement:
ALTER INDEX ALL ON table_name DISABLE;
If you disable an index, the query optimizer will not consider that disabled index for creating query execution
plans.
When you disable an index on a table, SQL Server keeps the index definition in the metadata and the index
statistics in nonclustered indexes. However, if you disable a nonclustered or clustered index on a view, SQL
Server will physically delete all the index data.
If you disable a clustered index of a table, you cannot access the table data using data manipulation language
such as SELECT, INSERT, UPDATE, and DELETE until you rebuild or drop the index.
SQL Server disable index examples
Let us take some examples of disabling indexes to have a better understanding.
A) Disabling an index example
This example uses the ALTER INDEX to disable the ix_cust_city index on the sales.customers table:
ALTER INDEX ix_cust_city ON sales.customers DISABLE;
As a result, the following query, which finds customers who locate in San Jose , cannot leverage the disabled
index:
SELECT first_name, last_name, city
FROM sales.customers
WHERE city = 'San Jose';

Here is the estimated query execution plan:

B) Disabling all indexes of a table example


This statement disables all indexes of the sales.customers table:
ALTER INDEX ALL ON sales.customers DISABLE;
Enable Index
This statement uses the ALTER INDEX statement to enable an index on a table:
ALTER INDEX index_name ON table_name REBUILD;
This statement uses the CREATE INDEX statement to enable the disabled index and recreate it:
CREATE INDEX index_name ON table_name(column_list) WITH(DROP_EXISTING=ON)
The following statement uses the ALTER INDEX statement to enable all disabled indexes on a table:
ALTER INDEX ALL ON table_name REBUILD;
Enable indexes using DBCC DBREINDEX statement
This statement uses the DBCC DBREINDEX to enable an index on a table:
DBCC DBREINDEX (table_name, index_name);
This statement uses the DBCC DBREINDEX to enable all indexes on a table:
DBCC DBREINDEX (table_name, " ");
Example
ALTER INDEX ALL ON sales.customers REBUILD;
Drop Index
The DROP INDEX statement removes one or more indexes from the current database. Here is the syntax of
the DROP INDEX statement:
DROP INDEX [IF EXISTS] index_name ON table_name;
In this syntax:
 First, specify the name of the index that you want to remove after the DROP INDEX clause.
 Second, specify the name of the table to which the index belongs.
Removing a nonexistent index will result in an error. However, you can use the IF EXISTS option to
conditionally drop the index and avoid the error.
Note that the IF EXISTS option has been available since SQL Server 2016 (13.x).
The DROP INDEX statement does not remove indexes created by PRIMARY KEY or UNIQUE constraints. To
drop indexes associated with these constraints, you use the ALTER TABLE DROP CONSTRAINT statement.
To remove multiple indexes from one or more tables at the same time, you specify a comma-separated list of
index names with the corresponding table names after the DROP INDEX clause as shown in the following
query:
DROP INDEX [IF EXISTS]
index_name1 ON table_name1,
index_name2 ON table_name2,
...;
A) Using SQL Server DROP INDEX to remove one index example
This statement uses the DROP INDEX statement to remove the ix_cust_email index from the sales.customers
table:
DROP INDEX IF EXISTS ix_cust_email ON sales.customers;
B) Using SQL Server DROP INDEX to remove multiple indexes example
The following example uses the DROP INDEX statement to remove the ix_cust_city, ix_cust_fullname indexes
from the sales.customers table:
DROP INDEX ix_cust_city ON sales.customers, ix_cust_fullname ON sales.customers;

You might also like