SQL Server 2005 Performance Diagnosis and Tuning using SQL ...

786 views
695 views

Published on

0 Comments
1 Like
Statistics
Notes
  • Be the first to comment

No Downloads
Views
Total views
786
On SlideShare
0
From Embeds
0
Number of Embeds
1
Actions
Shares
0
Downloads
24
Comments
0
Likes
1
Embeds 0
No embeds

No notes for slide
  • Management Studio provides many reports out-of-box. Select instance name in the node and choose Summary from View menu. Server Dashboard report gives good overview of the instance configuration and instance activity. See Activity Details. Observe scheduled Agent jobs, blocked transactions and breakdown of CPU among databases Server Configuration Changes report. It reports all changes made via sp_configure and Trace flag changes. Schema Changes History report gives all DDL changes made to the schema such as index creates, index drops etc and ALTER DATABASE commands. Memory Consumption report gives memory consumption by component, distribution of memory allocation buffer pages and memory changes over time. Activity – All Blocking Transactions gives you details of all blocked transactions and the TSQL statements that are being blocked Activity – TopSessions gives you list of Top Sessions ordered by CPU, Reads and Writes Top Transactions by Age shows you longest running transactions. Observe the Isolation Levels of these transactions. Performance – Batch Execution Statistics Database-level Reports – Disk Usage
  • Note: In the wall clock time interval of 10 minutes between 50 to 60, SQL1 spent 10 minutes and SQL2 spent 10 minutes. This is possible on a single CPU box if each of these statements spent time blocking on something.
  • Run
  • First of all, missing indexes is not a recommendation. Missing indexes identifies indexes, had they existed, would have been useed by query optimizer and would have improved performance of just that query. Adding indices may potentially hurt performance of inserts, updates and deletes. Measure impact of existing indeces by using index_usage_stats. So monitor adding an index using index usage stats.
  • First of all, missing indexes is not a recommendation. Missing indexes identifies indexes, had they existed, would have been useed by query optimizer and would have improved performance of just that query. Adding indices may potentially hurt performance of inserts, updates and deletes. Measure impact of existing indeces by using index_usage_stats. So monitor adding an index using index usage stats.
  • USE AdventureWorks GO IF OBJECTPROPERTY(object_id('NewCustomer'), 'IsUserTable') = 1 DROP TABLE NewCustomer SELECT * INTO NewCustomer FROM Sales.Customer GO IF OBJECTPROPERTY(object_id('NewCustomerAddress'), 'IsUserTable') = 1 DROP TABLE NewCustomerAddress SELECT * INTO NewCustomerAddress FROM Sales.CustomerAddress GO IF OBJECTPROPERTY(object_id('NewAddress'), 'IsUserTable') = 1 DROP TABLE NewAddress SELECT * INTO NewAddress FROM Person.Address GO IF OBJECTPROPERTY(object_id('NewVendor'), 'IsUserTable') = 1 DROP TABLE NewVendor SELECT * INTO NewVendor FROM Purchasing.Vendor GO IF OBJECTPROPERTY(object_id('NewVendorContact'), 'IsUserTable') = 1 DROP TABLE NewVendorContact SELECT * INTO NewVendorContact FROM Purchasing.VendorContact GO IF OBJECTPROPERTY(object_id('NewIndividual'), 'IsUserTable') = 1 DROP TABLE NewIndividual SELECT * INTO NewIndividual FROM Sales.Individual GO CREATE INDEX [IDX_NewIndividual_CustID] ON [dbo].[NewIndividual] ([CustomerID]) IF OBJECTPROPERTY(object_id('NewEmployee'), 'IsUserTable') = 1 DROP TABLE NewEmployee SELECT * INTO NewEmployee FROM HumanResources.Employee GO IF OBJECTPROPERTY(object_id('NewSalesOrderHeader'), 'IsUserTable') = 1 DROP TABLE NewSalesOrderHeader SELECT * INTO NewSalesOrderHeader FROM Sales.SalesOrderHeader GO IF OBJECTPROPERTY(object_id('NewSalesOrderDetail'), 'IsUserTable') = 1 DROP TABLE NewSalesOrderDetail SELECT * INTO NewSalesOrderDetail FROM Sales.SalesOrderDetail GO IF OBJECTPROPERTY(object_id('NewProduct'), 'IsUserTable') = 1 DROP TABLE NewProduct SELECT * INTO NewProduct FROM Production.Product -- Insert million rows in NewAddress table BEGIN TRANSACTION DEMO DECLARE @iNewRows int DECLARE @CustID int DECLARE @TerrID int SELECT @iNewRows = 1 --SELECT @CustID = (SELECT max(CustomerID) FROM NewCustomer) + 1 --SELECT @TerrID = 1 -- WHILE (@iNewRows < 1000001) BEGIN INSERT /* 8 */ INTO NewAddress (AddressLine1, City, StateProvinceID, PostalCode, rowguid, ModifiedDate) VALUES ( '13747 Street of the Dreams', 'Redmond', 15, 98052, newid(), getdate()) SELECT @iNewRows = @iNewRows + 1 END COMMIT TRANSACTION DEMO CREATE CLUSTERED INDEX [_dta_index_NewAddress_c_8_727673640__K1] ON [dbo].[NewAddress] ( [AddressID] ASC )WITH (SORT_IN_TEMPDB = OFF, DROP_EXISTING = OFF, IGNORE_DUP_KEY = OFF, ONLINE = OFF) ON [PRIMARY] -- CREATE Database Snapshots USE [master] GO /****** Object: Database [Snapshots] Script Date: 08/04/2005 14:31:08 ******/ CREATE DATABASE [Snapshots] ON PRIMARY ( NAME = N'Snapshots', FILENAME = N'C:Program FilesMicrosoft SQL ServerMSSQL.1MSSQLDATASnapshots.mdf' , SIZE = 2048KB , MAXSIZE = UNLIMITED, FILEGROWTH = 1024KB ) LOG ON ( NAME = N'Snapshots_log', FILENAME = N'C:Program FilesMicrosoft SQL ServerMSSQL.1MSSQLDATASnapshots_log.ldf' , SIZE = 1024KB , MAXSIZE = 2048GB , FILEGROWTH = 10%) COLLATE SQL_Latin1_General_CP1_CI_AS GO EXEC dbo.sp_dbcmptlevel @dbname=N'Snapshots', @new_cmptlevel=90 GO IF (1 = FULLTEXTSERVICEPROPERTY('IsFullTextInstalled')) begin EXEC [Snapshots].[dbo].[sp_fulltext_database] @action = 'disable' end GO ALTER DATABASE [Snapshots] SET ANSI_NULL_DEFAULT OFF GO ALTER DATABASE [Snapshots] SET ANSI_NULLS OFF GO ALTER DATABASE [Snapshots] SET ANSI_PADDING OFF GO ALTER DATABASE [Snapshots] SET ANSI_WARNINGS OFF GO ALTER DATABASE [Snapshots] SET ARITHABORT OFF GO ALTER DATABASE [Snapshots] SET AUTO_CLOSE OFF GO ALTER DATABASE [Snapshots] SET AUTO_CREATE_STATISTICS ON GO ALTER DATABASE [Snapshots] SET AUTO_SHRINK OFF GO ALTER DATABASE [Snapshots] SET AUTO_UPDATE_STATISTICS ON GO ALTER DATABASE [Snapshots] SET CURSOR_CLOSE_ON_COMMIT OFF GO ALTER DATABASE [Snapshots] SET CURSOR_DEFAULT GLOBAL GO ALTER DATABASE [Snapshots] SET CONCAT_NULL_YIELDS_NULL OFF GO ALTER DATABASE [Snapshots] SET NUMERIC_ROUNDABORT OFF GO ALTER DATABASE [Snapshots] SET QUOTED_IDENTIFIER OFF GO ALTER DATABASE [Snapshots] SET RECURSIVE_TRIGGERS OFF GO ALTER DATABASE [Snapshots] SET ENABLE_BROKER GO ALTER DATABASE [Snapshots] SET AUTO_UPDATE_STATISTICS_ASYNC OFF GO ALTER DATABASE [Snapshots] SET DATE_CORRELATION_OPTIMIZATION OFF GO ALTER DATABASE [Snapshots] SET TRUSTWORTHY OFF GO ALTER DATABASE [Snapshots] SET ALLOW_SNAPSHOT_ISOLATION OFF GO ALTER DATABASE [Snapshots] SET PARAMETERIZATION SIMPLE GO ALTER DATABASE [Snapshots] SET READ_WRITE GO ALTER DATABASE [Snapshots] SET RECOVERY FULL GO ALTER DATABASE [Snapshots] SET MULTI_USER GO ALTER DATABASE [Snapshots] SET PAGE_VERIFY CHECKSUM GO ALTER DATABASE [Snapshots] SET DB_CHAINING OFF -- Use Database Snapshots -- USE Snapshots GO IF OBJECTPROPERTY(object_id('NewVendor'), 'IsUserTable') = 1 DROP TABLE NewVendor SELECT * INTO NewVendor FROM AdventureWorks.Purchasing.Vendor GO
  • USE [msdb] GO /****** Object: Job [Demo] Script Date: 08/03/2005 04:33:22 ******/ IF EXISTS (SELECT job_id FROM msdb.dbo.sysjobs_view WHERE(name = N'Demo') EXEC msdb.dbo.sp_delete_job @job_name=N'Demo', @delete_unused_schedule=1 USE [msdb] GO DECLARE @jobId BINARY(16) EXEC msdb.dbo.sp_add_job @job_name=N'Demo', @enabled=1, @notify_level_eventlog=0, @notify_level_email=2, @notify_level_netsend=2, @notify_level_page=2, @delete_level=0, @description=N'Demo scheduled job', @category_name=N'[Uncategorized (Local)]', @owner_login_name=N'REDMONDvshah', @job_id = @jobId OUTPUT select @jobId GO EXEC msdb.dbo.sp_add_jobserver @job_name=N'Demo', @server_name = N'MICROSOF-4C50F0TECHREADY' GO USE [msdb] GO EXEC msdb.dbo.sp_add_jobstep @job_name=N'Demo', @step_name=N's1', @step_id=1, @cmdexec_success_code=0, @on_success_action=1, @on_fail_action=2, @retry_attempts=0, @retry_interval=0, @os_run_priority=0, @subsystem=N'TSQL', @command=N'select getdate()', @database_name=N'AdventureWorks', @flags=0 GO USE [msdb] GO EXEC msdb.dbo.sp_update_job @job_name=N'Demo', @enabled=1, @start_step_id=1, @notify_level_eventlog=0, @notify_level_email=2, @notify_level_netsend=2, @notify_level_page=2, @delete_level=0, @description=N'Demo scheduled job', @category_name=N'[Uncategorized (Local)]', @owner_login_name=N'REDMONDvshah', @notify_email_operator_name=N'', @notify_netsend_operator_name=N'', @notify_page_operator_name=N'' GO USE [msdb] GO DECLARE @schedule_id int EXEC msdb.dbo.sp_add_jobschedule @job_name=N'Demo', @name=N'schedule1', @enabled=1, @freq_type=8, @freq_interval=1, @freq_subday_type=1, @freq_subday_interval=0, @freq_relative_interval=0, @freq_recurrence_factor=1, @active_start_date=20050803, @active_end_date=99991231, @active_start_time=10000, @active_end_time=235959, @schedule_id = @schedule_id OUTPUT select @schedule_id GO
  • Use AdventureWorks GO --Author: Vipul Shah -- Version: 2 -- -- This code is provided "AS IS" with no warranties, and confers no rights. -- Use of included script samples are subject to the terms specified at http://www.microsoft.com/info/cpyright.htm -- -- THIS CODE IS NOT TESTED. IT JUST SHOWS PROOF-OF-CONCEPT. -- -- SET ANSI_NULLS ON SET QUOTED_IDENTIFIER ON GO -- Convert SQL Handle, Start and End Offsets to SQL Text CREATE FUNCTION [dbo].[GetSqlTextFromBatchText](@BatchText [nvarchar](max), @StartOffset [int], @EndOffset [int]) RETURNS [nvarchar](4000) WITH EXECUTE AS CALLER AS BEGIN --NVarChar are unicode characters which take up two bytes DECLARE @Result nvarchar(4000) --If @Stop is -1, set the byte offset to twice the number of --characters in the NVarChar @batch IF (@EndOffset = -1) SET @EndOffset = len(@BatchText) * 2 --Convert byte offset to Unicode character length SET @Result = SUBSTRING(@BatchText, @StartOffset / 2, (@EndOffset - @StartOffset) / 2) RETURN @Result END GO -- -- Take two snapshots of dm_exec_query_stats that are SnapshotInterval apart and show results -- ALTER PROCEDURE [dbo].[QueryStatsDelta] @SnapshotInterval [datetime] WITH EXECUTE AS CALLER AS BEGIN TRANSACTION --Take first snapshot SELECT * INTO #tmpDmExecQueryStats0 FROM sys.dm_exec_query_stats SELECT * INTO #tmpDmOsWaitStats0 FROM sys.dm_os_wait_stats WAITFOR DELAY @SnapshotInterval --Take second snapshot SELECT * INTO #tmpDmExecQueryStats1 FROM sys.dm_exec_query_stats SELECT * INTO #tmpDmOsWaitStats1 FROM sys.dm_os_wait_stats -- --Take delta of the two snapshots --Show Top queries ordered by elapsed time -- SELECT [dbo].GetSqlTextFromBatchText(CAST(sql_batch.text as nvarchar(max)), t1.statement_start_offset, t1.statement_end_offset) "SQL Text", -- t1.sql_handle, -- t1.statement_start_offset, -- t1.statement_end_offset, -- t1.plan_generation_num "Plan Gen Num", t1.plan_handle, -- t1.creation_time, -- t0.last_execution_time, -- t1.last_execution_time, -- t1.last_execution_time - t0.last_execution_time, -- t0_Execution_Count = CASE t0.execution_count WHEN NULL THEN 0 ELSE t0.execution_count END, -- t1.execution_count "t1 Execution Count", (t1.execution_count - (CASE WHEN t0.execution_count IS NULL THEN 0 ELSE t0.execution_count END)) "Delta Executions", -- t0_Elapsed_time = CASE t0.total_elapsed_time WHEN NULL THEN 0 ELSE t0.total_elapsed_time END, -- t1.total_elapsed_time "t1 Elapsed Time", delta_elapsed = (t1.total_elapsed_time - (CASE WHEN t0.total_elapsed_time IS NULL THEN 0 ELSE t0.total_elapsed_time END)), -- t0_CPU_Time = CASE t0.total_worker_time WHEN NULL THEN 0 ELSE t0.total_worker_time END, -- t1.total_worker_time "t1 CPU Time", (t1.total_worker_time - (CASE WHEN t0.total_worker_time IS NULL THEN 0 ELSE t0.total_worker_time END)) "Delta CPU Time", -- t0_Physical_reads = CASE t0.total_physical_reads WHEN NULL THEN 0 ELSE t0.total_physical_reads END, -- t1.total_physical_reads, (t1.total_physical_reads - (CASE WHEN t0.total_physical_reads IS NULL THEN 0 ELSE t0.total_physical_reads END)) "Delta Physical Reads", -- t0_Logical_writes = CASE t0.total_logical_writes WHEN NULL THEN 0 ELSE t0.total_logical_writes END, -- t1.total_logical_writes, (t1.total_logical_writes - (CASE WHEN t0.total_logical_writes IS NULL THEN 0 ELSE t0.total_logical_writes END)) "Delta Logical Writes", -- t0_Logical_reads = CASE t0.total_logical_reads WHEN NULL THEN 0 ELSE t0.total_logical_reads END, -- t1.total_logical_reads, (t1.total_logical_reads - (CASE WHEN t0.total_logical_reads IS NULL THEN 0 ELSE t0.total_logical_reads END)) "Delta Logical Reads" -- t0_CLR_Time = CASE t0.total_clr_time WHEN NULL THEN 0 ELSE t0.total_clr_time END -- t1.total_clr_time, -- t1.total_clr_time - t0.total_clr_time, FROM #tmpDmExecQueryStats0 t0 RIGHT OUTER JOIN #tmpDmExecQueryStats1 t1 CROSS APPLY sys.dm_exec_sql_text(t1.sql_handle) sql_batch ON t1.sql_handle = t0.sql_handle AND t1.plan_handle = t0.plan_handle AND t1.statement_start_offset = t0.statement_start_offset AND t1.statement_end_offset = t0.statement_end_offset ORDER BY delta_elapsed DESC SELECT * FROM ( SELECT x1.wait_type, delta_wait_time_ms = (x1.wait_time_ms - (CASE WHEN x0.wait_time_ms IS NULL THEN 0 ELSE x0.wait_time_ms END)) FROM #tmpDmOsWaitStats0 x0 RIGHT OUTER JOIN #tmpDmOsWaitStats1 x1 ON x1.wait_type = x0.wait_type ) y WHERE y.wait_type NOT IN ('CLR_SEMAPHORE','LAZYWRITER_SLEEP','RESOURCE_QUEUE','SLEEP_TASK','SLEEP_SYSTEMTASK','WAITFOR','SQLTRACE_BUFFER_FLUSH') ORDER BY y.delta_wait_time_ms DESC ROLLBACK TRANSACTION RETURN
  • USE AdventureWorks GO DECLARE @i int SELECT @i = 1 WHILE (@i <= 3) BEGIN SELECT /* 1 */ City, NumberOfOrders = count(*) FROM NewIndividual i JOIN NewCustomer c ON i.CustomerID = c.CustomerID AND c.CustomerType = 'I' JOIN NewCustomerAddress ca ON ca.CustomerID = c.CustomerID JOIN NewAddress a ON a.AddressID = ca.AddressID JOIN NewSalesOrderHeader sh ON c.CustomerID = sh.CustomerID JOIN NewSalesOrderDetail sd ON sd.SalesOrderID = sh.SalesOrderID JOIN NewProduct p ON p.ProductID = sd.ProductID WHERE StateProvinceID = (SELECT StateProvinceID FROM Person.StateProvince WHERE StateProvinceCode = 'CA') GROUP BY City ORDER BY 2 DESC SELECT /* 2 */ i.CustomerID, c.ModifiedDate, City FROM NewIndividual i JOIN NewCustomer c ON i.CustomerID = c.CustomerID AND c.CustomerType = 'I' JOIN NewCustomerAddress ca ON ca.CustomerID = c.CustomerID JOIN NewAddress a ON a.AddressID = ca.AddressID WHERE i.CustomerID > 13000 AND i.CustomerID < 22000 SELECT /* 3 */ i.CustomerID, c.ModifiedDate, City FROM NewIndividual i JOIN NewCustomer c ON i.CustomerID = c.CustomerID AND c.CustomerType = 'I' JOIN NewCustomerAddress ca ON ca.CustomerID = c.CustomerID JOIN NewAddress a ON a.AddressID = ca.AddressID WHERE i.CustomerID = 16701 SELECT /* 4 */ i.CustomerID, c.TerritoryID, City FROM NewIndividual i JOIN NewCustomer c ON i.CustomerID = c.CustomerID AND c.CustomerType = 'I' JOIN NewCustomerAddress ca ON ca.CustomerID = c.CustomerID JOIN NewAddress a ON a.AddressID = ca.AddressID WHERE StateProvinceID = (SELECT StateProvinceID FROM Person.StateProvince WHERE StateProvinceCode = 'CA') --AND c.SalesPersonID <> null ORDER BY i.CustomerID, City SELECT /* 5 */ x.total_price, a.AddressLine1, a.AddressLine2, a.City FROM (SELECT sum(d.UnitPrice) total_price, d.SalesOrderID FROM NewSalesOrderDetail d, (SELECT SalesOrderID FROM dbo.NewSalesOrderHeader WHERE OnlineOrderFlag = 'True') s WHERE d.SalesOrderId = s.SalesOrderId GROUP BY d.SalesOrderID ) x, dbo.NewSalesOrderHeader h, dbo.NewCustomer c, dbo.NewAddress a WHERE x.SalesOrderID = h.SalesOrderID AND h.CustomerID = c.CustomerID AND c.TerritoryID = a.AddressID SELECT /* 6 */ AddressLine1, AddressLine2, City FROM NewAddress WHERE ((StateProvinceID > 0 AND StateProvinceID < 12) OR (StateProvinceID > 49 AND StateProvinceID < 76)) AND City LIKE '%x%' SELECT @i = @i + 1 END GO
  • Use AdventureWorks Go SELECT /* 1 */ City, NumberOfOrders = count(*) FROM NewIndividual i JOIN NewCustomer c ON i.CustomerID = c.CustomerID AND c.CustomerType = 'I' JOIN NewCustomerAddress ca ON ca.CustomerID = c.CustomerID JOIN NewAddress a ON a.AddressID = ca.AddressID JOIN NewSalesOrderHeader sh ON c.CustomerID = sh.CustomerID JOIN NewSalesOrderDetail sd ON sd.SalesOrderID = sh.SalesOrderID JOIN NewProduct p ON p.ProductID = sd.ProductID WHERE StateProvinceID = (SELECT StateProvinceID FROM Person.StateProvince WHERE StateProvinceCode = 'CA') GROUP BY City ORDER BY 2 DESC SELECT /* 2 */ i.CustomerID, c.ModifiedDate, City FROM NewIndividual i JOIN NewCustomer c ON i.CustomerID = c.CustomerID AND c.CustomerType = 'I' JOIN NewCustomerAddress ca ON ca.CustomerID = c.CustomerID JOIN NewAddress a ON a.AddressID = ca.AddressID WHERE i.CustomerID > 13000 AND i.CustomerID < 22000 SELECT /* 3 */ i.CustomerID, c.ModifiedDate, City FROM NewIndividual i JOIN NewCustomer c ON i.CustomerID = c.CustomerID AND c.CustomerType = 'I' JOIN NewCustomerAddress ca ON ca.CustomerID = c.CustomerID JOIN NewAddress a ON a.AddressID = ca.AddressID WHERE i.CustomerID = 16701 SELECT /* 4 */ i.CustomerID, c.TerritoryID, City FROM NewIndividual i JOIN NewCustomer c ON i.CustomerID = c.CustomerID AND c.CustomerType = 'I' JOIN NewCustomerAddress ca ON ca.CustomerID = c.CustomerID JOIN NewAddress a ON a.AddressID = ca.AddressID WHERE StateProvinceID = (SELECT StateProvinceID FROM Person.StateProvince WHERE StateProvinceCode = 'CA') --AND c.SalesPersonID <> null ORDER BY i.CustomerID, City SELECT /* 5 */ x.total_price, a.AddressLine1, a.AddressLine2, a.City FROM (SELECT sum(d.UnitPrice) total_price, d.SalesOrderID FROM NewSalesOrderDetail d, (SELECT SalesOrderID FROM dbo.NewSalesOrderHeader WHERE OnlineOrderFlag = 'True') s WHERE d.SalesOrderId = s.SalesOrderId GROUP BY d.SalesOrderID ) x, dbo.NewSalesOrderHeader h, dbo.NewCustomer c, dbo.NewAddress a WHERE x.SalesOrderID = h.SalesOrderID AND h.CustomerID = c.CustomerID AND c.TerritoryID = a.AddressID SELECT /* 6 */ AddressLine1, AddressLine2, City FROM NewAddress WHERE ((StateProvinceID > 0 AND StateProvinceID < 12) OR (StateProvinceID > 49 AND StateProvinceID < 76)) AND City LIKE '%x%' GO SELECT /* 1 */ City, NumberOfOrders = count(*) FROM NewIndividual i JOIN NewCustomer c ON i.CustomerID = c.CustomerID AND c.CustomerType = 'I' JOIN NewCustomerAddress ca ON ca.CustomerID = c.CustomerID JOIN NewAddress a ON a.AddressID = ca.AddressID JOIN NewSalesOrderHeader sh ON c.CustomerID = sh.CustomerID JOIN NewSalesOrderDetail sd ON sd.SalesOrderID = sh.SalesOrderID JOIN NewProduct p ON p.ProductID = sd.ProductID WHERE StateProvinceID = (SELECT StateProvinceID FROM Person.StateProvince WHERE StateProvinceCode = 'CA') GROUP BY City ORDER BY 2 DESC SELECT /* 2 */ i.CustomerID, c.ModifiedDate, City FROM NewIndividual i JOIN NewCustomer c ON i.CustomerID = c.CustomerID AND c.CustomerType = 'I' JOIN NewCustomerAddress ca ON ca.CustomerID = c.CustomerID JOIN NewAddress a ON a.AddressID = ca.AddressID WHERE i.CustomerID > 13000 AND i.CustomerID < 22000 SELECT /* 3 */ i.CustomerID, c.ModifiedDate, City FROM NewIndividual i JOIN NewCustomer c ON i.CustomerID = c.CustomerID AND c.CustomerType = 'I' JOIN NewCustomerAddress ca ON ca.CustomerID = c.CustomerID JOIN NewAddress a ON a.AddressID = ca.AddressID WHERE i.CustomerID = 16701 SELECT /* 4 */ i.CustomerID, c.TerritoryID, City FROM NewIndividual i JOIN NewCustomer c ON i.CustomerID = c.CustomerID AND c.CustomerType = 'I' JOIN NewCustomerAddress ca ON ca.CustomerID = c.CustomerID JOIN NewAddress a ON a.AddressID = ca.AddressID WHERE StateProvinceID = (SELECT StateProvinceID FROM Person.StateProvince WHERE StateProvinceCode = 'CA') --AND c.SalesPersonID <> null ORDER BY i.CustomerID, City SELECT /* 5 */ x.total_price, a.AddressLine1, a.AddressLine2, a.City FROM (SELECT sum(d.UnitPrice) total_price, d.SalesOrderID FROM NewSalesOrderDetail d, (SELECT SalesOrderID FROM dbo.NewSalesOrderHeader WHERE OnlineOrderFlag = 'True') s WHERE d.SalesOrderId = s.SalesOrderId GROUP BY d.SalesOrderID ) x, dbo.NewSalesOrderHeader h, dbo.NewCustomer c, dbo.NewAddress a WHERE x.SalesOrderID = h.SalesOrderID AND h.CustomerID = c.CustomerID AND c.TerritoryID = a.AddressID SELECT /* 6 */ AddressLine1, AddressLine2, City FROM NewAddress WHERE ((StateProvinceID > 0 AND StateProvinceID < 12) OR (StateProvinceID > 49 AND StateProvinceID < 76)) AND City LIKE '%x%' GO SELECT /* 1 */ City, NumberOfOrders = count(*) FROM NewIndividual i JOIN NewCustomer c ON i.CustomerID = c.CustomerID AND c.CustomerType = 'I' JOIN NewCustomerAddress ca ON ca.CustomerID = c.CustomerID JOIN NewAddress a ON a.AddressID = ca.AddressID JOIN NewSalesOrderHeader sh ON c.CustomerID = sh.CustomerID JOIN NewSalesOrderDetail sd ON sd.SalesOrderID = sh.SalesOrderID JOIN NewProduct p ON p.ProductID = sd.ProductID WHERE StateProvinceID = (SELECT StateProvinceID FROM Person.StateProvince WHERE StateProvinceCode = 'CA') GROUP BY City ORDER BY 2 DESC SELECT /* 2 */ i.CustomerID, c.ModifiedDate, City FROM NewIndividual i JOIN NewCustomer c ON i.CustomerID = c.CustomerID AND c.CustomerType = 'I' JOIN NewCustomerAddress ca ON ca.CustomerID = c.CustomerID JOIN NewAddress a ON a.AddressID = ca.AddressID WHERE i.CustomerID > 13000 AND i.CustomerID < 22000 SELECT /* 3 */ i.CustomerID, c.ModifiedDate, City FROM NewIndividual i JOIN NewCustomer c ON i.CustomerID = c.CustomerID AND c.CustomerType = 'I' JOIN NewCustomerAddress ca ON ca.CustomerID = c.CustomerID JOIN NewAddress a ON a.AddressID = ca.AddressID WHERE i.CustomerID = 16701 SELECT /* 4 */ i.CustomerID, c.TerritoryID, City FROM NewIndividual i JOIN NewCustomer c ON i.CustomerID = c.CustomerID AND c.CustomerType = 'I' JOIN NewCustomerAddress ca ON ca.CustomerID = c.CustomerID JOIN NewAddress a ON a.AddressID = ca.AddressID WHERE StateProvinceID = (SELECT StateProvinceID FROM Person.StateProvince WHERE StateProvinceCode = 'CA') --AND c.SalesPersonID <> null ORDER BY i.CustomerID, City SELECT /* 5 */ x.total_price, a.AddressLine1, a.AddressLine2, a.City FROM (SELECT sum(d.UnitPrice) total_price, d.SalesOrderID FROM NewSalesOrderDetail d, (SELECT SalesOrderID FROM dbo.NewSalesOrderHeader WHERE OnlineOrderFlag = 'True') s WHERE d.SalesOrderId = s.SalesOrderId GROUP BY d.SalesOrderID ) x, dbo.NewSalesOrderHeader h, dbo.NewCustomer c, dbo.NewAddress a WHERE x.SalesOrderID = h.SalesOrderID AND h.CustomerID = c.CustomerID AND c.TerritoryID = a.AddressID SELECT /* 6 */ AddressLine1, AddressLine2, City FROM NewAddress WHERE ((StateProvinceID > 0 AND StateProvinceID < 12) OR (StateProvinceID > 49 AND StateProvinceID < 76)) AND City LIKE '%x%' GO BEGIN TRANSACTION DEMO INSERT /* 8 */ INTO NewAddress (AddressLine1, City, StateProvinceID, PostalCode, rowguid, ModifiedDate) VALUES ( '13747 Street of the Dreams', 'Redmond', 15, 98052, newid(), getdate()) UPDATE /* 8 */ NewAddress SET City = 'Bothell' WHERE City = 'Redmond' INSERT /* 8 */ INTO NewAddress (AddressLine1, City, StateProvinceID, PostalCode, rowguid, ModifiedDate) VALUES ( '13747 Street of the Dreams', 'Redmond', 15, 98052, newid(), getdate()) INSERT /* 8 */ INTO NewAddress (AddressLine1, City, StateProvinceID, PostalCode, rowguid, ModifiedDate) VALUES ( '13747 Street of the Dreams', 'Redmond', 15, 98052, newid(), getdate()) UPDATE /* 8 */ NewAddress SET City = 'Sammamish' WHERE City = 'Bothell' INSERT /* 8 */ INTO NewAddress (AddressLine1, City, StateProvinceID, PostalCode, rowguid, ModifiedDate) VALUES ( '13747 Street of the Dreams', 'Redmond', 15, 98052, newid(), getdate()) INSERT /* 8 */ INTO NewAddress (AddressLine1, City, StateProvinceID, PostalCode, rowguid, ModifiedDate) VALUES ( '13747 Street of the Dreams', 'Redmond', 15, 98052, newid(), getdate()) UPDATE /* 8 */ NewAddress SET City = 'Issaquah' WHERE City = 'Sammamish' INSERT /* 8 */ INTO NewAddress (AddressLine1, City, StateProvinceID, PostalCode, rowguid, ModifiedDate) VALUES ( '13747 Street of the Dreams', 'Redmond', 15, 98052, newid(), getdate()) INSERT /* 8 */ INTO NewAddress (AddressLine1, City, StateProvinceID, PostalCode, rowguid, ModifiedDate) VALUES ( '13747 Street of the Dreams', 'Redmond', 15, 98052, newid(), getdate()) INSERT /* 8 */ INTO NewAddress (AddressLine1, City, StateProvinceID, PostalCode, rowguid, ModifiedDate) VALUES ( '13747 Street of the Dreams', 'Redmond', 15, 98052, newid(), getdate()) INSERT /* 8 */ INTO NewAddress (AddressLine1, City, StateProvinceID, PostalCode, rowguid, ModifiedDate) VALUES ( '13747 Street of the Dreams', 'Redmond', 15, 98052, newid(), getdate()) UPDATE /* 8 */ NewAddress SET City = 'Medina' WHERE City = 'Issaquah' INSERT /* 8 */ INTO NewAddress (AddressLine1, City, StateProvinceID, PostalCode, rowguid, ModifiedDate) VALUES ( '13747 Street of the Dreams', 'Redmond', 15, 98052, newid(), getdate()) INSERT /* 8 */ INTO NewAddress (AddressLine1, City, StateProvinceID, PostalCode, rowguid, ModifiedDate) VALUES ( '13747 Street of the Dreams', 'Redmond', 15, 98052, newid(), getdate()) INSERT /* 8 */ INTO NewAddress (AddressLine1, City, StateProvinceID, PostalCode, rowguid, ModifiedDate) VALUES ( '13747 Street of the Dreams', 'Redmond', 15, 98052, newid(), getdate()) INSERT /* 8 */ INTO NewAddress (AddressLine1, City, StateProvinceID, PostalCode, rowguid, ModifiedDate) VALUES ( '13747 Street of the Dreams', 'Redmond', 15, 98052, newid(), getdate()) UPDATE /* 8 */ NewAddress SET City = 'Clyde Hill' WHERE City = 'Medina' INSERT /* 8 */ INTO NewAddress (AddressLine1, City, StateProvinceID, PostalCode, rowguid, ModifiedDate) VALUES ( '13747 Street of the Dreams', 'Redmond', 15, 98052, newid(), getdate()) INSERT /* 8 */ INTO NewAddress (AddressLine1, City, StateProvinceID, PostalCode, rowguid, ModifiedDate) VALUES ( '13747 Street of the Dreams', 'Redmond', 15, 98052, newid(), getdate()) INSERT /* 8 */ INTO NewAddress (AddressLine1, City, StateProvinceID, PostalCode, rowguid, ModifiedDate) VALUES ( '13747 Street of the Dreams', 'Redmond', 15, 98052, newid(), getdate()) INSERT /* 8 */ INTO NewAddress (AddressLine1, City, StateProvinceID, PostalCode, rowguid, ModifiedDate) VALUES ( '13747 Street of the Dreams', 'Redmond', 15, 98052, newid(), getdate()) INSERT /* 8 */ INTO NewAddress (AddressLine1, City, StateProvinceID, PostalCode, rowguid, ModifiedDate) VALUES ( '13747 Street of the Dreams', 'Redmond', 15, 98052, newid(), getdate()) INSERT /* 8 */ INTO NewAddress (AddressLine1, City, StateProvinceID, PostalCode, rowguid, ModifiedDate) VALUES ( '13747 Street of the Dreams', 'Redmond', 15, 98052, newid(), getdate()) INSERT /* 8 */ INTO NewAddress (AddressLine1, City, StateProvinceID, PostalCode, rowguid, ModifiedDate) VALUES ( '13747 Street of the Dreams', 'Redmond', 15, 98052, newid(), getdate()) INSERT /* 8 */ INTO NewAddress (AddressLine1, City, StateProvinceID, PostalCode, rowguid, ModifiedDate) VALUES ( '13747 Street of the Dreams', 'Redmond', 15, 98052, newid(), getdate()) INSERT /* 8 */ INTO NewAddress (AddressLine1, City, StateProvinceID, PostalCode, rowguid, ModifiedDate) VALUES ( '13747 Street of the Dreams', 'Redmond', 15, 98052, newid(), getdate()) INSERT /* 8 */ INTO NewAddress (AddressLine1, City, StateProvinceID, PostalCode, rowguid, ModifiedDate) VALUES ( '13747 Street of the Dreams', 'Redmond', 15, 98052, newid(), getdate()) INSERT /* 8 */ INTO NewAddress (AddressLine1, City, StateProvinceID, PostalCode, rowguid, ModifiedDate) VALUES ( '13747 Street of the Dreams', 'Redmond', 15, 98052, newid(), getdate()) INSERT /* 8 */ INTO NewAddress (AddressLine1, City, StateProvinceID, PostalCode, rowguid, ModifiedDate) VALUES ( '13747 Street of the Dreams', 'Redmond', 15, 98052, newid(), getdate()) INSERT /* 8 */ INTO NewAddress (AddressLine1, City, StateProvinceID, PostalCode, rowguid, ModifiedDate) VALUES ( '13747 Street of the Dreams', 'Redmond', 15, 98052, newid(), getdate()) INSERT /* 8 */ INTO NewAddress (AddressLine1, City, StateProvinceID, PostalCode, rowguid, ModifiedDate) VALUES ( '13747 Street of the Dreams', 'Redmond', 15, 98052, newid(), getdate()) INSERT /* 8 */ INTO NewAddress (AddressLine1, City, StateProvinceID, PostalCode, rowguid, ModifiedDate) VALUES ( '13747 Street of the Dreams', 'Redmond', 15, 98052, newid(), getdate()) INSERT /* 8 */ INTO NewAddress (AddressLine1, City, StateProvinceID, PostalCode, rowguid, ModifiedDate) VALUES ( '13747 Street of the Dreams', 'Redmond', 15, 98052, newid(), getdate()) INSERT /* 8 */ INTO NewAddress (AddressLine1, City, StateProvinceID, PostalCode, rowguid, ModifiedDate) VALUES ( '13747 Street of the Dreams', 'Redmond', 15, 98052, newid(), getdate()) INSERT /* 8 */ INTO NewAddress (AddressLine1, City, StateProvinceID, PostalCode, rowguid, ModifiedDate) VALUES ( '13747 Street of the Dreams', 'Redmond', 15, 98052, newid(), getdate()) INSERT /* 8 */ INTO NewAddress (AddressLine1, City, StateProvinceID, PostalCode, rowguid, ModifiedDate) VALUES ( '13747 Street of the Dreams', 'Redmond', 15, 98052, newid(), getdate()) INSERT /* 8 */ INTO NewAddress (AddressLine1, City, StateProvinceID, PostalCode, rowguid, ModifiedDate) VALUES ( '13747 Street of the Dreams', 'Redmond', 15, 98052, newid(), getdate()) INSERT /* 8 */ INTO NewAddress (AddressLine1, City, StateProvinceID, PostalCode, rowguid, ModifiedDate) VALUES ( '13747 Street of the Dreams', 'Redmond', 15, 98052, newid(), getdate()) INSERT /* 8 */ INTO NewAddress (AddressLine1, City, StateProvinceID, PostalCode, rowguid, ModifiedDate) VALUES ( '13747 Street of the Dreams', 'Redmond', 15, 98052, newid(), getdate()) INSERT /* 8 */ INTO NewAddress (AddressLine1, City, StateProvinceID, PostalCode, rowguid, ModifiedDate) VALUES ( '13747 Street of the Dreams', 'Redmond', 15, 98052, newid(), getdate()) INSERT /* 8 */ INTO NewAddress (AddressLine1, City, StateProvinceID, PostalCode, rowguid, ModifiedDate) VALUES ( '13747 Street of the Dreams', 'Redmond', 15, 98052, newid(), getdate()) INSERT /* 8 */ INTO NewAddress (AddressLine1, City, StateProvinceID, PostalCode, rowguid, ModifiedDate) VALUES ( '13747 Street of the Dreams', 'Redmond', 15, 98052, newid(), getdate()) INSERT /* 8 */ INTO NewAddress (AddressLine1, City, StateProvinceID, PostalCode, rowguid, ModifiedDate) VALUES ( '13747 Street of the Dreams', 'Redmond', 15, 98052, newid(), getdate()) INSERT /* 8 */ INTO NewAddress (AddressLine1, City, StateProvinceID, PostalCode, rowguid, ModifiedDate) VALUES ( '13747 Street of the Dreams', 'Redmond', 15, 98052, newid(), getdate()) INSERT /* 8 */ INTO NewAddress (AddressLine1, City, StateProvinceID, PostalCode, rowguid, ModifiedDate) VALUES ( '13747 Street of the Dreams', 'Redmond', 15, 98052, newid(), getdate()) INSERT /* 8 */ INTO NewAddress (AddressLine1, City, StateProvinceID, PostalCode, rowguid, ModifiedDate) VALUES ( '13747 Street of the Dreams', 'Redmond', 15, 98052, newid(), getdate()) INSERT /* 8 */ INTO NewAddress (AddressLine1, City, StateProvinceID, PostalCode, rowguid, ModifiedDate) VALUES ( '13747 Street of the Dreams', 'Redmond', 15, 98052, newid(), getdate()) INSERT /* 8 */ INTO NewAddress (AddressLine1, City, StateProvinceID, PostalCode, rowguid, ModifiedDate) VALUES ( '13747 Street of the Dreams', 'Redmond', 15, 98052, newid(), getdate()) INSERT /* 8 */ INTO NewAddress (AddressLine1, City, StateProvinceID, PostalCode, rowguid, ModifiedDate) VALUES ( '13747 Street of the Dreams', 'Redmond', 15, 98052, newid(), getdate()) INSERT /* 8 */ INTO NewAddress (AddressLine1, City, StateProvinceID, PostalCode, rowguid, ModifiedDate) VALUES ( '13747 Street of the Dreams', 'Redmond', 15, 98052, newid(), getdate()) INSERT /* 8 */ INTO NewAddress (AddressLine1, City, StateProvinceID, PostalCode, rowguid, ModifiedDate) VALUES ( '13747 Street of the Dreams', 'Redmond', 15, 98052, newid(), getdate()) INSERT /* 8 */ INTO NewAddress (AddressLine1, City, StateProvinceID, PostalCode, rowguid, ModifiedDate) VALUES ( '13747 Street of the Dreams', 'Redmond', 15, 98052, newid(), getdate()) INSERT /* 8 */ INTO NewAddress (AddressLine1, City, StateProvinceID, PostalCode, rowguid, ModifiedDate) VALUES ( '13747 Street of the Dreams', 'Redmond', 15, 98052, newid(), getdate()) INSERT /* 8 */ INTO NewAddress (AddressLine1, City, StateProvinceID, PostalCode, rowguid, ModifiedDate) VALUES ( '13747 Street of the Dreams', 'Redmond', 15, 98052, newid(), getdate()) INSERT /* 8 */ INTO NewAddress (AddressLine1, City, StateProvinceID, PostalCode, rowguid, ModifiedDate) VALUES ( '13747 Street of the Dreams', 'Redmond', 15, 98052, newid(), getdate()) INSERT /* 8 */ INTO NewAddress (AddressLine1, City, StateProvinceID, PostalCode, rowguid, ModifiedDate) VALUES ( '13747 Street of the Dreams', 'Redmond', 15, 98052, newid(), getdate()) INSERT /* 8 */ INTO NewAddress (AddressLine1, City, StateProvinceID, PostalCode, rowguid, ModifiedDate) VALUES ( '13747 Street of the Dreams', 'Redmond', 15, 98052, newid(), getdate()) INSERT /* 8 */ INTO NewAddress (AddressLine1, City, StateProvinceID, PostalCode, rowguid, ModifiedDate) VALUES ( '13747 Street of the Dreams', 'Redmond', 15, 98052, newid(), getdate()) INSERT /* 8 */ INTO NewAddress (AddressLine1, City, StateProvinceID, PostalCode, rowguid, ModifiedDate) VALUES ( '13747 Street of the Dreams', 'Redmond', 15, 98052, newid(), getdate()) INSERT /* 8 */ INTO NewAddress (AddressLine1, City, StateProvinceID, PostalCode, rowguid, ModifiedDate) VALUES ( '13747 Street of the Dreams', 'Redmond', 15, 98052, newid(), getdate()) INSERT /* 8 */ INTO NewAddress (AddressLine1, City, StateProvinceID, PostalCode, rowguid, ModifiedDate) VALUES ( '13747 Street of the Dreams', 'Redmond', 15, 98052, newid(), getdate()) INSERT /* 8 */ INTO NewAddress (AddressLine1, City, StateProvinceID, PostalCode, rowguid, ModifiedDate) VALUES ( '13747 Street of the Dreams', 'Redmond', 15, 98052, newid(), getdate()) INSERT /* 8 */ INTO NewAddress (AddressLine1, City, StateProvinceID, PostalCode, rowguid, ModifiedDate) VALUES ( '13747 Street of the Dreams', 'Redmond', 15, 98052, newid(), getdate()) INSERT /* 8 */ INTO NewAddress (AddressLine1, City, StateProvinceID, PostalCode, rowguid, ModifiedDate) VALUES ( '13747 Street of the Dreams', 'Redmond', 15, 98052, newid(), getdate()) INSERT /* 8 */ INTO NewAddress (AddressLine1, City, StateProvinceID, PostalCode, rowguid, ModifiedDate) VALUES ( '13747 Street of the Dreams', 'Redmond', 15, 98052, newid(), getdate()) INSERT /* 8 */ INTO NewAddress (AddressLine1, City, StateProvinceID, PostalCode, rowguid, ModifiedDate) VALUES ( '13747 Street of the Dreams', 'Redmond', 15, 98052, newid(), getdate()) INSERT /* 8 */ INTO NewAddress (AddressLine1, City, StateProvinceID, PostalCode, rowguid, ModifiedDate) VALUES ( '13747 Street of the Dreams', 'Redmond', 15, 98052, newid(), getdate()) INSERT /* 8 */ INTO NewAddress (AddressLine1, City, StateProvinceID, PostalCode, rowguid, ModifiedDate) VALUES ( '13747 Street of the Dreams', 'Redmond', 15, 98052, newid(), getdate()) INSERT /* 8 */ INTO NewAddress (AddressLine1, City, StateProvinceID, PostalCode, rowguid, ModifiedDate) VALUES ( '13747 Street of the Dreams', 'Redmond', 15, 98052, newid(), getdate()) INSERT /* 8 */ INTO NewAddress (AddressLine1, City, StateProvinceID, PostalCode, rowguid, ModifiedDate) VALUES ( '13747 Street of the Dreams', 'Redmond', 15, 98052, newid(), getdate()) INSERT /* 8 */ INTO NewAddress (AddressLine1, City, StateProvinceID, PostalCode, rowguid, ModifiedDate) VALUES ( '13747 Street of the Dreams', 'Redmond', 15, 98052, newid(), getdate()) INSERT /* 8 */ INTO NewAddress (AddressLine1, City, StateProvinceID, PostalCode, rowguid, ModifiedDate) VALUES ( '13747 Street of the Dreams', 'Redmond', 15, 98052, newid(), getdate()) INSERT /* 8 */ INTO NewAddress (AddressLine1, City, StateProvinceID, PostalCode, rowguid, ModifiedDate) VALUES ( '13747 Street of the Dreams', 'Redmond', 15, 98052, newid(), getdate()) INSERT /* 8 */ INTO NewAddress (AddressLine1, City, StateProvinceID, PostalCode, rowguid, ModifiedDate) VALUES ( '13747 Street of the Dreams', 'Redmond', 15, 98052, newid(), getdate()) INSERT /* 8 */ INTO NewAddress (AddressLine1, City, StateProvinceID, PostalCode, rowguid, ModifiedDate) VALUES ( '13747 Street of the Dreams', 'Redmond', 15, 98052, newid(), getdate()) INSERT /* 8 */ INTO NewAddress (AddressLine1, City, StateProvinceID, PostalCode, rowguid, ModifiedDate) VALUES ( '13747 Street of the Dreams', 'Redmond', 15, 98052, newid(), getdate()) INSERT /* 8 */ INTO NewAddress (AddressLine1, City, StateProvinceID, PostalCode, rowguid, ModifiedDate) VALUES ( '13747 Street of the Dreams', 'Redmond', 15, 98052, newid(), getdate()) INSERT /* 8 */ INTO NewAddress (AddressLine1, City, StateProvinceID, PostalCode, rowguid, ModifiedDate) VALUES ( '13747 Street of the Dreams', 'Redmond', 15, 98052, newid(), getdate()) INSERT /* 8 */ INTO NewAddress (AddressLine1, City, StateProvinceID, PostalCode, rowguid, ModifiedDate) VALUES ( '13747 Street of the Dreams', 'Redmond', 15, 98052, newid(), getdate()) INSERT /* 8 */ INTO NewAddress (AddressLine1, City, StateProvinceID, PostalCode, rowguid, ModifiedDate) VALUES ( '13747 Street of the Dreams', 'Redmond', 15, 98052, newid(), getdate()) INSERT /* 8 */ INTO NewAddress (AddressLine1, City, StateProvinceID, PostalCode, rowguid, ModifiedDate) VALUES ( '13747 Street of the Dreams', 'Redmond', 15, 98052, newid(), getdate()) INSERT /* 8 */ INTO NewAddress (AddressLine1, City, StateProvinceID, PostalCode, rowguid, ModifiedDate) VALUES ( '13747 Street of the Dreams', 'Redmond', 15, 98052, newid(), getdate()) INSERT /* 8 */ INTO NewAddress (AddressLine1, City, StateProvinceID, PostalCode, rowguid, ModifiedDate) VALUES ( '13747 Street of the Dreams', 'Redmond', 15, 98052, newid(), getdate()) INSERT /* 8 */ INTO NewAddress (AddressLine1, City, StateProvinceID, PostalCode, rowguid, ModifiedDate) VALUES ( '13747 Street of the Dreams', 'Redmond', 15, 98052, newid(), getdate()) INSERT /* 8 */ INTO NewAddress (AddressLine1, City, StateProvinceID, PostalCode, rowguid, ModifiedDate) VALUES ( '13747 Street of the Dreams', 'Redmond', 15, 98052, newid(), getdate()) INSERT /* 8 */ INTO NewAddress (AddressLine1, City, StateProvinceID, PostalCode, rowguid, ModifiedDate) VALUES ( '13747 Street of the Dreams', 'Redmond', 15, 98052, newid(), getdate()) INSERT /* 8 */ INTO NewAddress (AddressLine1, City, StateProvinceID, PostalCode, rowguid, ModifiedDate) VALUES ( '13747 Street of the Dreams', 'Redmond', 15, 98052, newid(), getdate()) INSERT /* 8 */ INTO NewAddress (AddressLine1, City, StateProvinceID, PostalCode, rowguid, ModifiedDate) VALUES ( '13747 Street of the Dreams', 'Redmond', 15, 98052, newid(), getdate()) INSERT /* 8 */ INTO NewAddress (AddressLine1, City, StateProvinceID, PostalCode, rowguid, ModifiedDate) VALUES ( '13747 Street of the Dreams', 'Redmond', 15, 98052, newid(), getdate()) INSERT /* 8 */ INTO NewAddress (AddressLine1, City, StateProvinceID, PostalCode, rowguid, ModifiedDate) VALUES ( '13747 Street of the Dreams', 'Redmond', 15, 98052, newid(), getdate()) INSERT /* 8 */ INTO NewAddress (AddressLine1, City, StateProvinceID, PostalCode, rowguid, ModifiedDate) VALUES ( '13747 Street of the Dreams', 'Redmond', 15, 98052, newid(), getdate()) INSERT /* 8 */ INTO NewAddress (AddressLine1, City, StateProvinceID, PostalCode, rowguid, ModifiedDate) VALUES ( '13747 Street of the Dreams', 'Redmond', 15, 98052, newid(), getdate()) INSERT /* 8 */ INTO NewAddress (AddressLine1, City, StateProvinceID, PostalCode, rowguid, ModifiedDate) VALUES ( '13747 Street of the Dreams', 'Redmond', 15, 98052, newid(), getdate()) INSERT /* 8 */ INTO NewAddress (AddressLine1, City, StateProvinceID, PostalCode, rowguid, ModifiedDate) VALUES ( '13747 Street of the Dreams', 'Redmond', 15, 98052, newid(), getdate()) INSERT /* 8 */ INTO NewAddress (AddressLine1, City, StateProvinceID, PostalCode, rowguid, ModifiedDate) VALUES ( '13747 Street of the Dreams', 'Redmond', 15, 98052, newid(), getdate()) INSERT /* 8 */ INTO NewAddress (AddressLine1, City, StateProvinceID, PostalCode, rowguid, ModifiedDate) VALUES ( '13747 Street of the Dreams', 'Redmond', 15, 98052, newid(), getdate()) INSERT /* 8 */ INTO NewAddress (AddressLine1, City, StateProvinceID, PostalCode, rowguid, ModifiedDate) VALUES ( '13747 Street of the Dreams', 'Redmond', 15, 98052, newid(), getdate()) INSERT /* 8 */ INTO NewAddress (AddressLine1, City, StateProvinceID, PostalCode, rowguid, ModifiedDate) VALUES ( '13747 Street of the Dreams', 'Redmond', 15, 98052, newid(), getdate()) INSERT /* 8 */ INTO NewAddress (AddressLine1, City, StateProvinceID, PostalCode, rowguid, ModifiedDate) VALUES ( '13747 Street of the Dreams', 'Redmond', 15, 98052, newid(), getdate()) INSERT /* 8 */ INTO NewAddress (AddressLine1, City, StateProvinceID, PostalCode, rowguid, ModifiedDate) VALUES ( '13747 Street of the Dreams', 'Redmond', 15, 98052, newid(), getdate()) INSERT /* 8 */ INTO NewAddress (AddressLine1, City, StateProvinceID, PostalCode, rowguid, ModifiedDate) VALUES ( '13747 Street of the Dreams', 'Redmond', 15, 98052, newid(), getdate()) INSERT /* 8 */ INTO NewAddress (AddressLine1, City, StateProvinceID, PostalCode, rowguid, ModifiedDate) VALUES ( '13747 Street of the Dreams', 'Redmond', 15, 98052, newid(), getdate()) INSERT /* 8 */ INTO NewAddress (AddressLine1, City, StateProvinceID, PostalCode, rowguid, ModifiedDate) VALUES ( '13747 Street of the Dreams', 'Redmond', 15, 98052, newid(), getdate()) INSERT /* 8 */ INTO NewAddress (AddressLine1, City, StateProvinceID, PostalCode, rowguid, ModifiedDate) VALUES ( '13747 Street of the Dreams', 'Redmond', 15, 98052, newid(), getdate()) COMMIT TRANSACTION DEMO GO
  • checkpoint dbcc dropcleanbuffers dbcc freeproccache Use AdventureWorks GO exec dbo.QueryStatsDelta @SnapshotInterval='00:00:20' select * from sys.dm_exec_sql_text() select * from sys.dm_exec_query_plan() sp_configure SELECT * FROM sys.configurations ORDER BY name GO sp_configure 'show advanced options', 1 go reconfigure go sp_configure 'blocked process threshold', 2 go reconfigure go
  • USE Snapshots -- Update two vendors to have a ActiveFlag of false -- Update Vendor contact for each of those vendors to have a ContactTypeID of 'owner' GO SELECT ActiveFlag FROM NewVendor WHERE VendorID > 0
  • USE Snapshots -- Update two vendors to have a ActiveFlag of false -- Update Vendor contact for each of those vendors to have a ContactTypeID of 'owner' GO set transaction isolation level repeatable read go ALTER DATABASE Snapshots SET read_committed_snapshot O FF GO alter database Snapshots set allow_snapshot_isolation OFF go -- Execute the BEGIN TRAN and the first UPDATE BEGIN TRAN UPDATE NewVendor SET ActiveFlag = 'TRUE' WHERE VendorID > 0 WAITFOR DELAY '00:00:05' ROLLBACK
  • USE AdventureWorks -- Update two vendors to have a ActiveFlag of false -- Update Vendor contact for each of those vendors to have a ContactTypeID of 'owner' GO -- Execute the BEGIN TRAN and the first UPDATE BEGIN TRAN UPDATE NewVendor SET ActiveFlag = 'False' WHERE VendorID = 1 -------- Only execute up to this point in the first batch ---- -------------------------------------------------------------- ------- Next, start execution here ---------------------- UPDATE NewVendorContact SET ContactTypeID = (SELECT ContactTypeID FROM Person.ContactType WHERE Name = 'Owner') WHERE VendorID = 1 -------- Only execute up to this point in the next batch ------ -------------------------------------------------------------- ROLLBACK TRAN -- --The following transaction will be executed on another connection --BEGIN TRAN -- UPDATE NewVendorContact -- SET ContactTypeID = (SELECT ContactTypeID FROM ContactType -- WHERE Name = 'Owner') -- WHERE VendorID = 15 -- UPDATE NewVendor -- SET ActiveFlag = 'False' -- WHERE VendorID = 15 --COMMIT TRAN
  • USE AdventureWorks GO BEGIN TRAN UPDATE NewVendorContact SET ContactTypeID = (SELECT ContactTypeID FROM Person.ContactType WHERE Name = 'Owner') WHERE VendorID = 15 -------- Only execute up to this point in the first batch ---- -------------------------------------------------------------- -------- Next, start execution here ---------------------- UPDATE NewVendor SET ActiveFlag = 'False' WHERE VendorID = 15 -------- Only execute up to this point in the next batch ------ -------------------------------------------------------------- ROLLBACK Tran COMMIT TRAN
  • SQL Server 2005 Performance Diagnosis and Tuning using SQL ...

    1. 1. SQL Server 2005 Performance Diagnosis and Tuning using SQL Tools and DMVs <ul><li>Shawn Nesser </li></ul><ul><li>(Borrowed from Vipul Shah) </li></ul>
    2. 2. Session Objectives And Key Takeaways <ul><li>Session Objectives: </li></ul><ul><ul><li>How Tools and DMVs can be used to monitor and tune SQL Server 2005 </li></ul></ul><ul><ul><li>Walk away with demo scripts you can use </li></ul></ul><ul><li>Key Takeaways: </li></ul><ul><ul><li>Maximize benefit from Tools and DMVs for monitoring and tuning SQL Server 2005 </li></ul></ul>
    3. 3. Agenda <ul><li>New Capabilities in SQL Server 2005 </li></ul><ul><li>Management Studio Reports </li></ul><ul><li>Identify Top SQL (delta) </li></ul><ul><li>I/O Tuning </li></ul><ul><li>Contention Tuning </li></ul><ul><li>SQL Server Profiler </li></ul><ul><li>Demo Code is at end of slides (see Notes) </li></ul>
    4. 4. New Capabilities in SQL 2005? <ul><li>Dynamic Management Views (DMVs) </li></ul><ul><ul><li>Views on memory structures in the Engine </li></ul></ul><ul><ul><li>Monitor activity inside the Engine </li></ul></ul><ul><li>Trace Events </li></ul><ul><ul><li>New trace events that complete the picture provided by DMVs </li></ul></ul><ul><ul><li>Light-weight, ON-by-default trace to capture schema and configuration changes </li></ul></ul><ul><li>Dedicated Administration Connection </li></ul>
    5. 5. New Capabilities in SQL 2005? (continued) <ul><li>Database Engine Tuning Advisor </li></ul><ul><ul><li>Gives Partitions recommendations </li></ul></ul><ul><ul><li>Indexes and Indexed Views recommendations </li></ul></ul><ul><ul><li>Statistics recommendations </li></ul></ul><ul><ul><li>Tunes multiple databases </li></ul></ul><ul><ul><li>Time-bound and Storage-bound tuning </li></ul></ul><ul><li>XML ShowPlan </li></ul><ul><ul><li>MissingIndexes tag </li></ul></ul><ul><ul><ul><li>Indexes that query optimizer would use if available </li></ul></ul></ul>
    6. 6. New Capabilities in SQL 2005? (continued) <ul><li>Management Studio contains performance reports </li></ul><ul><ul><li>Reports are available at server level </li></ul></ul><ul><ul><li>Reports are available at database level </li></ul></ul><ul><li>SQL Server Profiler allows for correlation with Performance Counters </li></ul><ul><ul><li>Enhances ability to isolate problems </li></ul></ul>
    7. 7. Database Management Views <ul><li>Views built on top of internal structures </li></ul><ul><li>Ideal for tracking performance </li></ul><ul><ul><li>dm_repl_* </li></ul></ul><ul><ul><ul><li>Replication </li></ul></ul></ul><ul><ul><li>dm_broker_* </li></ul></ul><ul><ul><ul><li>SQL Service Broker </li></ul></ul></ul><ul><ul><li>dm_fts_* </li></ul></ul><ul><ul><ul><li>Full Text Search </li></ul></ul></ul><ul><ul><li>dm_qn_* </li></ul></ul><ul><ul><ul><li>Query Notifications </li></ul></ul></ul><ul><ul><li>dm_clr_* </li></ul></ul><ul><ul><ul><li>Common Language Runtime </li></ul></ul></ul><ul><ul><li>dm_exec_* </li></ul></ul><ul><ul><ul><li>Execution of user code and associated connections </li></ul></ul></ul><ul><ul><li>dm_os_* </li></ul></ul><ul><ul><ul><li>Memory, locking & scheduling </li></ul></ul></ul><ul><ul><li>dm_tran_* </li></ul></ul><ul><ul><ul><li>Transactions & isolation </li></ul></ul></ul><ul><ul><li>dm_io_* </li></ul></ul><ul><ul><ul><li>I/O on network and disks </li></ul></ul></ul><ul><ul><li>dm_db_* </li></ul></ul><ul><ul><ul><li>Databases and database objects </li></ul></ul></ul>Component Level Server Level
    8. 8. Default Trace <ul><li>Light-weight tracing is ON by default </li></ul><ul><li>Captures schema changes and configuration changes </li></ul><ul><li>Trace is captured in rolling window of 5 trace files 20MB each (maximum of 100MB) </li></ul><ul><ul><li>Old trace files are deleted </li></ul></ul><ul><ul><li>100MB limit is never exceeded </li></ul></ul><ul><ul><li>New trace file is created after every re-start </li></ul></ul><ul><ul><li>No more than 5 trace files are available </li></ul></ul>
    9. 9. Management Studio Reports <ul><li>Reports get data from DMVs and Default Trace files </li></ul><ul><li>Use these Reports for an overview </li></ul><ul><li>Server-level Reports </li></ul><ul><ul><li>Select SQL Server instance node in Object Explorer, select View  Summary menu, and Report drop-list </li></ul></ul><ul><li>Database-level Reports </li></ul><ul><ul><li>Select a database node in Object Explorer, select View  Summary menu, and Report drop-list </li></ul></ul>
    10. 11. Management Studio Reports Vipul Shah Program Manager SQL Server
    11. 12. Tracking Server Activity <ul><li>Track activity by Wait types </li></ul><ul><ul><li>Waits indicate where server spends its activity </li></ul></ul><ul><ul><li>Focus on wait event with highest wait time </li></ul></ul><ul><li>Track SQL statements </li></ul><ul><li>How do you track Top SQL and Waits? </li></ul><ul><ul><li>“ Performance – Top Queries” report in Management Studio shows you top queries since instance start time </li></ul></ul><ul><ul><li>Use DMVs to track activity in an interval </li></ul></ul><ul><ul><ul><li>QueryStatsDelta script is an example </li></ul></ul></ul>
    12. 13. Tracking Server Activity (continued) <ul><ul><li>“ QueryStatsDelta” script </li></ul></ul><ul><ul><ul><li>Uses dm_exec_query_stats </li></ul></ul></ul><ul><ul><ul><ul><li>Takes before and after snapshots and diffs them </li></ul></ul></ul></ul><ul><ul><ul><ul><li>Accounts for new statements in the interval </li></ul></ul></ul></ul><ul><ul><ul><ul><li>Orders top SQL by elapsed time </li></ul></ul></ul></ul><ul><ul><ul><ul><li>Shows exact SQL statement by extracting it from batch text </li></ul></ul></ul></ul><ul><ul><ul><li>Uses dm_os_wait_stats </li></ul></ul></ul><ul><ul><ul><ul><li>Takes before and after snapshots and diffs them </li></ul></ul></ul></ul><ul><ul><ul><ul><li>Removes Idle waits and Trace waits </li></ul></ul></ul></ul><ul><ul><ul><ul><li>Orders top wait events by wait duration </li></ul></ul></ul></ul>
    13. 15. Identify Top SQL Vipul Shah Program Manager SQL Server
    14. 16. Tuning I/O Intensive SQL <ul><ul><li>Use “MissingIndexes” tag in XML Show Plan for single statement-focused analysis </li></ul></ul><ul><ul><ul><li>Very useful when workload is not available or workload is incomplete </li></ul></ul></ul><ul><ul><ul><li>Missing indexes is NOT a recommendation </li></ul></ul></ul><ul><ul><ul><li>Optimizer would have used these indexes if available </li></ul></ul></ul><ul><ul><ul><li>Remember – creating these indexes may slow Inserts, Updates and Deletes </li></ul></ul></ul><ul><ul><ul><ul><li>Track index usage if you choose to create a missing index </li></ul></ul></ul></ul><ul><ul><ul><ul><li>Weight the costs-benefits of the index </li></ul></ul></ul></ul>
    15. 17. Tuning I/O Intensive SQL (continued) <ul><ul><li>Use Database Engine Tuning Advisor for comprehensive workload analysis </li></ul></ul><ul><ul><ul><li>Feed workload input to DTA </li></ul></ul></ul><ul><ul><ul><ul><li>Collect workload using “Tuning” template in SQL Server Profiler, or </li></ul></ul></ul></ul><ul><ul><ul><ul><li>Collect workload as SQL script </li></ul></ul></ul></ul><ul><ul><ul><li>Select the database for workload analysis </li></ul></ul></ul><ul><ul><ul><li>Select the databases to tune </li></ul></ul></ul><ul><ul><ul><li>Set a time-bound </li></ul></ul></ul><ul><ul><ul><li>Review output from analysis </li></ul></ul></ul><ul><ul><ul><li>Review reports to make educated choice </li></ul></ul></ul>
    16. 18. I/O Tuning Vipul Shah Program Manager SQL Server
    17. 19. How do I track index usage? <ul><li>How do I track index usage? </li></ul><ul><ul><li>Use dm_db_missing_index_group_stats, dm_db_missing_index_groups, dm_db_missing_indexes </li></ul></ul><ul><ul><li>Identify frequently used and less frequently used indexes </li></ul></ul><ul><ul><li>Do not drop index without careful consideration ! </li></ul></ul>
    18. 20. Detecting Contention <ul><li>“ Activity – All Blocking Transactions” report in Management Studio is excellent for seeing blocked transactions at that moment </li></ul><ul><li>“ Blocked Process Report” trace event </li></ul><ul><ul><li>To set 5 second blocked process report </li></ul></ul><ul><ul><ul><li>sp_configure 'blocked process threshold', 5 </li></ul></ul></ul><ul><li>“ Deadlock Graph” trace event </li></ul><ul><li>DMV dm_os_wait_stats shows aggregate duration spent on lock waits </li></ul>
    19. 21. Tuning Contention <ul><li>SQL Server 2000 – tradeoff between consistency and concurrency </li></ul><ul><li>SQL Server 2005 - use Row-Versioning based isolation levels </li></ul><ul><ul><li>Eliminates locking </li></ul></ul><ul><ul><li>Uses version store to keep old row versions </li></ul></ul><ul><ul><li>No tradeoff between consistency and concurrency </li></ul></ul><ul><ul><ul><li>Read Committed Snapshot isolation level </li></ul></ul></ul><ul><ul><ul><ul><li>Provides statement level consistency </li></ul></ul></ul></ul><ul><ul><ul><li>Snapshot isolation level </li></ul></ul></ul><ul><ul><ul><ul><li>Provides transaction level consistency </li></ul></ul></ul></ul>
    20. 22. Tuning Contention (continued) <ul><li>Use Read Committed Snapshot isolation level </li></ul><ul><ul><li>Most existing applications require no change </li></ul></ul><ul><ul><li>OFF by default </li></ul></ul><ul><ul><ul><li>Turn it ON per database </li></ul></ul></ul><ul><ul><li>Works with distributed transactions </li></ul></ul>
    21. 23. Detecting Contention and Deadlocks Vipul Shah Program Manager SQL Server
    22. 24. Performance Correlation in Profiler <ul><li>SQL Server Profiler </li></ul><ul><ul><li>Use to Trace events </li></ul></ul><ul><ul><li>Use to Replay events </li></ul></ul><ul><ul><li>Correlate Performance Counters to isolate problems quickly </li></ul></ul>
    23. 25. Performance Counter Correlation in Profiler Vipul Shah Program Manager SQL Server
    24. 26. Thank you! Thank you for attending this session and the 2005 PASS Community Summit in Grapevine! Please help us improve the quality of our conference by completing your session evaluation form. Completed evaluation forms may be given to the room monitor as you exit or to staff at the registration desk.
    25. 27. Create Tables <ul><li>Requires AdventureWorks database </li></ul><ul><li>Script is in Notes section </li></ul>Scripts
    26. 28. Create Scheduled Job <ul><li>Requires AdventureWorks database </li></ul><ul><li>Script is in Notes section </li></ul>Scripts
    27. 29. Create Stored Procedures <ul><li>Requires AdventureWorks database </li></ul><ul><li>Creates SPs and Functions for TopSQL and TopWaits </li></ul><ul><li>Script is in Notes section </li></ul>Scripts
    28. 30. Workload Without DML <ul><li>Requires AdventureWorks database </li></ul><ul><li>Script is in Notes section </li></ul>Scripts
    29. 31. Workload With DML <ul><li>Requires AdventureWorks database </li></ul><ul><li>Script is in Notes section </li></ul>Scripts
    30. 32. Demo Queries <ul><li>Requires AdventureWorks database </li></ul><ul><li>Script is in Notes section </li></ul>Scripts
    31. 33. Reader <ul><li>Requires Snapshots database </li></ul><ul><li>Script is in Notes section </li></ul>Scripts
    32. 34. Writer <ul><li>Requires Snapshots database </li></ul><ul><li>Script is in Notes section </li></ul>Scripts
    33. 35. First Part of Deadlock <ul><li>Requires AdventureWorks database </li></ul><ul><li>Script is in Notes section </li></ul>Scripts
    34. 36. Second Part of Deadlock <ul><li>Requires AdventureWorks database </li></ul><ul><li>Script is in Notes section </li></ul>Scripts
    35. 37. © 2005 Microsoft Corporation. All rights reserved. This presentation is for informational purposes only. Microsoft makes no warranties, express or implied, in this summary.

    ×