SQL Server sample code to differentiate the performance impact of SELECT *.
/* *************************** Create TestDB Database **************************** */
IF NOT EXISTS (SELECT [name] FROM master.[dbo].[sysdatabases] WHERE [name] = 'TestDB')
BEGIN
CREATE DATABASE [TestDB];
END
GO
USE [TestDB];
GO
/* *************************** Create TestTable Table ***************************** */
IF EXISTS (SELECT * FROM sys.sysobjects WHERE type = 'U'AND name = 'TestTable')
BEGIN
DROP TABLE [dbo].[TestTable];
END
CREATE TABLE [dbo].[TestTable]
(
[Id] [int] IDENTITY (1, 1) NOT NULL,
[Data] [int] NOT NULL,
[InsertedDate] [datetime] NOT NULL DEFAULT GETDATE()
)
IF EXISTS (SELECT name FROM sys.indexes WHERE name = N'PK_Individual_Id')
BEGIN
DROP INDEX PK_Individual_Id ON [dbo].[TestTable];
END
CREATE CLUSTERED INDEX PK_Individual_Id
ON [dbo].[TestTable] (Id);
GO
IF EXISTS (SELECT name FROM sys.indexes WHERE name = N'IX_Individual_Data')
BEGIN
DROP INDEX IX_Individual_Data ON [dbo].[TestTable];
END
CREATE NONCLUSTERED INDEX IX_Individual_Data
ON [dbo].[TestTable] (Data);
GO
/* ************************* Insert Test Data using CTE *************************** */
WITH TestData
AS (
-- Anchor Query
SELECT 1 AS SampleId, 1 AS SampleData
-- Union All
UNION ALL
-- Recursive Query
SELECT td.SampleId + 1, CAST(ABS(CHECKSUM(NEWID())) % 300 AS int)
FROM TestData td
WHERE td.SampleId < 30000
)
INSERT INTO [dbo].[TestTable] (Data)
SELECT SampleData
FROM TestData
OPTION (MAXRECURSION 30000);
GO 10
/* *************************** Clear Buffers and Cache **************************** */
DBCC FREESESSIONCACHE;
DBCC FREEPROCCACHE;
DBCC FREESYSTEMCACHE ('ALL');
DBCC DROPCLEANBUFFERS;
GO
/* *********************************************************************************
As we are requesting all the rows in the table, here a Clustered index scan is
inevitable. Examining Execution plan shows 81% of total cost towards batch. So
sending unnecessary data is going to give poor performance.
********************************************************************************* */
SELECT * FROM [dbo].[TestTable] WHERE [Data] = 251;
/* *************************** Clear Buffers and Cache **************************** */
DBCC FREESESSIONCACHE;
DBCC FREEPROCCACHE;
DBCC FREESYSTEMCACHE ('ALL');
DBCC DROPCLEANBUFFERS;
GO
/* *********************************************************************************
As we are only requesting only data which is present in the non-clustered index
itself. This query is not returning unnecessary data and will give more
performance. Examining Execution plan shows it got 0% cost towards complete
batch cost.
********************************************************************************* */
SELECT [Data] FROM [dbo].[TestTable] WHERE [Data] = 251;
/* **************************** Drop TestTable Table ****************************** */
IF EXISTS (SELECT * FROM sys.sysobjects WHERE type = 'U'AND name = 'TestTable')
BEGIN
DROP TABLE [dbo].[TestTable];
END
GO
/* **************************** Drop TestDB Database ***************************** */
USE master;
GO
IF EXISTS (SELECT [name] FROM master.[dbo].[sysdatabases] WHERE [name] = 'TestDB')
BEGIN
DROP DATABASE [TestDB];
END
GO