Monday, 1 February 2016

Too Many Indexes in SQL Server?


The saying “Too much of a good thing is not always good” holds true when discussing indexes. Too many indexes create additional overhead associated with the extra amount of data pages that the Query Optimizer needs to go through. Also, too many indexes require too much space and add to the time it takes to accomplish maintenance tasks.
Still, the Data Tuning Wizard typically recommends a large number of indexes, especially when analyzing a workload with many queries. The reason behind this is because queries are analyzed on an individual basis. It is a good practice to incrementally apply indexes as needed, always keeping a baseline to compare if the new index improves query performance.
SQL Server 2012 provides several Dynamic Management Views (DMV) to obtain index usage information. Some of these DMVs include:
•             sys.dm_db_missing_index_details: Returns detailed information about a missing index.
•             sys.dm_db_missing_index_columns: Returns information about the table columns that are missing an index.
•             sys.dm_db_missing_index_groups: Returns information about a specific group of missing indexes.
•             sys.dm_db_missing_index_group_stats: Returns summary information about missing index groups.
•             sys.dm_db_index_usage_stats: Returns counts of different types of index operations and the time each type of operation was last performed.
•             sys.dm_db_index_operational_stats: Returns current low-level I/O, locking, latching, and access method activity for each partition of a table or index in the database.
•             sys.dm_db_index_physical_stats: Returns size and fragmentation information for the data and indexes of the specified table or view.
For example, to obtain a list of indexes that have been used and those that have not been used by user queries, query the sys.dm_db_index_usage_stats DMV. From the list of indexes that have been used you can obtain important statistics that help you fine tune your indexes. Some of this information includes index access patterns such index scans, index seeks, and index bookmark lookups.
To obtain a list of indexes that have been used by user queries, execute the following script:

SELECT

 SO.name Object_Name,

 SCHEMA_NAME(SO.schema_id) Schema_name,

 SI.name Index_name,

 SI.Type_Desc,

 US.user_seeks,

 US.user_scans,

 US.user_lookups,

 US.user_updates

FROM sys.objects AS SO

 JOIN sys.indexes AS SI

  ON SO.object_id = SI.object_id

 INNER JOIN sys.dm_db_index_usage_stats AS US

  ON SI.object_id = SI.object_id 

  AND SI.index_id = SI.index_id

WHERE

 database_id=DB_ID(‘AdventureWorks’)

 SO.type = ‘u’

 AND SI.type IN (1, 2)

 AND (US.user_seeks > 0 OR US.user_scans > 0 OR US.user_lookups > 0 );


To obtain a list of indexes that have not been used by user queries, execute the following script:
SELECT

 SO.Name TableName,

 SI.name IndexName,

 SI.Type_Desc IndexType,

 US.user_updates

FROM sys.objects AS SO

 INNER JOIN sys.indexes AS SI

  ON SO.object_id = SI.object_id

 LEFT OUTER JOIN sys.dm_db_index_usage_stats AS US  

  ON SI.object_id = US.object_id 

  AND SI.index_id = US.index_id

WHERE

 database_id=DB_ID(‘AdventureWorks’)

 AND SO.type = ‘u’

 AND SI.type IN (1, 2)

 AND (US.index_id IS NULL)

 OR  (US.user_seeks = 0 AND US.user_scans = 0 AND US.user_lookups = 0 );

Indexes that are not used by user queries should be dropped, unless they have been added to support mission critical work that occurs at specific points in time, such as monthly or quarterly data extracts and reports. Unused indexes add overhead to insert, delete, and update operations as well as index maintenance operations. Index usage statistics are initialized to empty when the SQL Server service restarts. The database is detached or shutdown when the AUTO_CLOSE property is turned on.


Move from Scan to Seek


Yes, that’s the thumb rule to target while optimizing SQL Queries “Scans are bad, Seeks are good“.
Scan indicates reading the whole of the index/table looking for matches – the time this takes is proportional to the size of the index.
Seek, on the other hand, indicates b-tree structure of the index to seek directly to matching records – time taken is only proportional to the number of matching records.
In general an index seek is preferable to an index scan (when the number of matching records is proportionally much lower than the total number of records), as the time taken to perform an index seek is constant regardless of the total number of records in your table. However, in certain situations, an index scan can be faster than an index seek (sometimes significantly faster) – usually when the table is very small, or when a large percentage of the records match the predicate.

Scan
Seek
Heap
Table Scan
Clustered Index
Clustered Index Scan
Clustered Index Seek
Non-clustered Index
Index Scan
Index Seek



Table Scans: With no indexes defined/available at all that are relevant to your query the planner is forced to use a table scan meaning that every row is looked at. This can result in every page relating to the table’s data being read from disk (worst case scenario). However, for some queries, table scan is used even when a useful index is present – this is usually because the data in the table is so small that it is more hassle to traverse the indexes.
Index Scans: Reads the entire index—all the rows in the index order and occurs when an index exists that is only partially helpful.The index might only be partially helpful if there is relatively low selectivity in the distribution of the data. Index scan means the DB reads the data in an Index directly, when it finds what it wants in the Index , it uses the record addresses in the index to go to the table and read only what it requires.There’s a performance advantage to an index scan because an index tends to be much narrower than the full table column.
Clustered Index Scan: In a table without a clustered index (a heap table), data pages are not linked together – so traversing pages requires a lookup into the Index Allocation Map. A clustered table, however, has it’s data pages linked in a doubly linked list – making sequential scans a bit faster. Of course, in exchange, you have the overhead of dealing with keeping the data pages in order on INSERTs, UPDATEs, and DELETEs. A heap table, however, requires a second write to the Index Allocation Map.
Index Seeks: traverses a B-tree and walks through leaf nodes seeking only the matching or qualifying rows based on the filter criteria.  Only relevant index pages need to be read instead of every page in the index (or table).
Clustered Indexes: With a clustered index the table data is stored in the leaf nodes of that index instead of being in a separate heap structure. This means that there will never need to be any extra row lookups after finding rows using that index no matter what columns are needed [unless you have off-page data like TEXT columns or VARCHAR(MAX) columns containing large object (LOB) data types]. You can have only one clustered index for this reason, so chose the one carefully in order to get maximum gain.


How SQL Server 2012 Uses Indexes


A good understanding of how indexes are used by SQL Server is also important in a good index design. In SQL Server, the Query Optimizer component determines the most cost-effective option to execute a query. The Query Optimizer evaluates a number of query execution plans and selects the execution plan with the lowest cost.
The execution plan selected by the Query Optimizer may or may not make efficient use of indexes, or it may not use indexes at all. The following sections describe how execution plans can use indexes.
Table scan
Indexes are not required by SQL Server to retrieve data requested by a query. In the absence of indexes or if determined to be least cost effective, SQL server scans every row of a table until the query is satisfied. This is known as a table scan. As you may suspect, table scans can bring forth expensive IO operations for large tables. SQL Server has to read every single data page until it finds the data that satisfies the query. A table scan can take from a couple of seconds to several minutes. Some users may even experience time-outs by applications with short response-time thresholds.
Table scans generally occur when there is no clustered indexed available; in other words, when the table is a heap.
Index scan and index seek
An index scan is similar to a table scan in that SQL Server has to read every single data page in the index until it finds the data that satisfies the query. Index scans can be both IO and memory intensive operations.
An index seek on the other hand, is a more efficient way of retrieving data because only data pages and rows that satisfy the query are read. Index seeks result in less data pages read, hence reducing IO and memory consumption.
Depending on how selective a query is, meaning what percentage of the total number of rows in a table is requested, SQL Server Query Optimizer can choose to do an index scan rather than an index
seek. The tipping point at which an index scan is preferred by the SQL Server Query Optimizer is not always a definitive percentage. There are many factors such as parallelism settings, memory availability, and number of rows that contribute in the decision for the more cost-effective option.
Bookmark lookup
It is quite common to see queries that require additional columns than the ones included in a non-clustered index. To retrieve these additional columns, SQL Server needs to retrieve additional data pages to cover all requested columns. Bookmark lookups can become expensive operations when dealing with a large number of rows because more data pages need to be retrieved from disk and loaded into memory.
To avoid excessive bookmark lookup operations, the required columns that need to be covered by the query can be included in the index definition. These types of indexes are known as covering indexes.


How SQL Server Clustering Works

In this section, you consider active and passive nodes, the shared disk array, the quorum, public and private networks, and the cluster server. Then, you learn how a failover works.
Active Nodes Versus Passive Nodes
A Windows Failover Cluster can support up to sixteen nodes; however, most clustering deployment is only two nodes. A single SQL Server 2012 instance can run on only a single node at a time; and should a failover occur, the failed instance can failover to another node. Clusters of three or more physical nodes should be considered when you need to cluster many SQL Server instances.
In a two-node Windows Failover Cluster with SQL Server, one of the physical nodes is considered the active node, and the second one is the passive node for that single SQL Server instance. It doesn’t matter which of the physical servers in the cluster is designated as active or passive, but you should specifically assign one node as the active and the other as the passive. This way, there is no confusion about which physical server is performing which role at the current time.
When referring to an active node, this particular node is currently running a SQL Server instance accessing that instance’s databases, which are located on a shared disk array.
When referring to a passive node, this particular node is not currently running the SQL Server. When a node is passive, it is not running the production databases, but it is in a state of readiness. If the active node fails and a failover occurs, the passive node automatically runs production databases and begins serving user requests. In this case, the passive node has become active, and the formerly active node becomes the passive node (or the failed node, if a failure occurs that prevents it from operating).
Shared Disk Array
Standalone SQL Server instances usually store their databases on local disk storage or non-shared disk storage; clustered SQL Server instances store data on a shared disk array. Shared means that all nodes of the Windows Failover Cluster are physically connected to the shared disk array, but only the active node can access that instance’s databases. To ensure the integrity of the databases, both nodes of a cluster never access the shared disk at the same time.
Generally speaking, a shared disk array can be an iSCSI, a fiber-channel, SAS connected, a RAID 1, a RAID 5, or a RAID 10 disk array housed in a standalone unit, or a SAN. This shared disk array must have at least two logical disk partitions. One partition is used for storing the clustered instance’s SQL Server databases, and the other is used for the quorum drive, if a quorum drive is used. Additionally, you need a third logical partition if you choose to cluster MSDTC.
The Quorum
When both cluster nodes are up and running and participating in their respective active and passive roles, they communicate with each other over the network. For example, if you change a configuration setting on the active node, this configuration is propagated automatically, and quickly, to the passive node, thereby ensuring synchronization.
As you might imagine, though, you can make a change on the active node and have it fail before the change is sent over the network and made on the passive node. In this scenario, the change is never applied to the passive node. Depending on the nature of the change, this could cause problems, even causing both nodes of the cluster to fail.
To prevent this change from happening, a Windows Failover Cluster employs a quorum. A quorum is essentially a log file, similar in concept to database logs. Its purpose is to record any change made on the active node. This way, should any recorded change not get to the passive node because the active node has failed and cannot send the change to the passive node over the network, the passive node, when it becomes the active node, can read the quorum log file to find out what the change was. The passive node can then make the change before it becomes the new active node. If the state of this drive is compromised, your cluster may become inoperable.
In effect, each cluster quorum can cast one “vote,” where the majority of total votes (based on the number of these cluster quorums that are online) determine whether the cluster continues running on the cluster node. This prevents more than one cluster node attempting to take ownership of the same SQL Server instance. The voting quorums are cluster nodes or, in some cases, a disk witness or file share witness. Each voting cluster quorum (with the exception of a file share witness) contains a copy of the cluster configuration. The cluster service works to keep all copies synchronized at all times.
Following are the four supported Windows Failover Cluster quorum modes:
·         Node Majority: Each node that is available and in communication can vote. The cluster functions only with a majority of the votes.
·         Node and Disk Majority: Each node plus a designated disk in the cluster storage (the “disk witness”) can vote, whenever they are available and in communication. The cluster functions only with a majority of the votes.
·         Node and File Share Majority: Each node plus a designated file share created by the administrator (the “file share witness”) can vote, whenever they are available and in communication. The cluster functions only with a majority of the votes.
·         No Majority: Disk Only: The cluster has a quorum if one node is available and in communication with a specific disk in the cluster storage. Only the nodes that are also in communication with that disk can join the cluster. The disk is the single point of failure, so use highly reliable storage. A quorum drive is a logical drive on the shared disk array dedicated to storing the quorum and as a best practice should be around 1GB of fault tolerant disk storage.
With two-node clusters Disk only is the most often used quorum configuration, commonly known as the quorum disk. The quorum configuration can be switched after the cluster has been deployed based on the number of clustered nodes and user requirements. While in clusters with greater than two nodes, the other three quorum modes are more commonly used.

Public and Private Networks
Each node of a cluster must have at least two network cards to be a fully supported installation. One network card is connected to the public network, and the other network card will be connected to a private cluster network.
The public network is the network to which the client applications connect. This is how they communicate to a clustered SQL Server instance using the clustered IP address and clustered SQL Server name. It is recommended to have two teamed network cards for the public network for redundancy and to improve availability.
·         The private network is used solely for communications between the clustered nodes. It is used mainly for the heartbeat communication. Two forms of communications are executed:
·         LooksAlive: Verifies that the SQL Server service runs on the online node every 5 seconds by default
·         IsAlive: Verifies that SQL Server accepts connections by executing sp_server_diagnostics.
This health detection logic determines if a node is down and the passive node then takes over the production workload.
The SQL Server Instance
Surprisingly, SQL Server client applications don’t need to know how to switch communicating from a failed cluster node to the new active node or anything else about specific cluster nodes (such as the NETBIOS name or IP address of individual cluster nodes). This is because each clustered SQL Server instance is assigned a Network name and IP address, which client applications use to connect to the clustered SQL Server. In other words, client applications don’t connect to a node’s specific name or IP address but instead to the cluster SQL network name or cluster SQL IP address that stays consistent and fails over. Each clustered SQL Server will belong to a Failover Cluster Resource Group that contains the following resources that will fail together:
·         SQL Server Network Name
·         IP Address
·         One or more shared disks
·         SQL Server Database Engine service
·         SQL Server Agent
·         SQL Server Analysis Services, if installed in the same group
·         One file share resource, if the FILESTREAM feature is installed

How a Failover Works
Assume that a single SQL Server 2012 instance runs on the active node of a cluster and that a passive node is available to take over when needed. At this time, the active node communicates with both the database and the quorum on the shared disk array. Because only a single node at a time can access the shared disk array, the passive node does not access the database or the quorum. In addition, the active node sends out heartbeat signals over the private network, and the passive node monitors them, so it can take over if a failover occurs. Clients are also interacting with the active node via the clustered SQL Server name and IP address while running production workloads.
Now assume that the active node stops working because of a power failure. The passive node, which is monitoring the heartbeats from the active node, notices that the heartbeats stopped. After a predetermined delay, the passive node assumes that the active node has failed and initiates a failover. As part of the failover process, the passive node (now the active node) takes over control of the shared disk array and reads the quorum, looking for any unsynchronized configuration changes. It also takes over control of the clustered SQL Server name and IP address. In addition, as the node takes over the databases, it has to perform a SQL Server startup and recover the databases.
The time this takes depends on many factors, including the performance of the hardware and the number of transactions that might have to be rolled forward or back during the database recovery process. When the recovery process is complete, the new active node announces itself on the network with the clustered SQL Server name and IP address, which enables the client applications to reconnect and begin using the SQL Server 2012 instance after this minimal interruption.