“Magic numbers”, local variable and performance Як стиль написання запитів впливає на швидкодію системи Андрій Зробок azrobok@gmail.com
Need Java / NET programmer Java/NET programming – 80% SQL programming – 20% Framework Query builder Simple queries etc. 2 | 4/7/2019 | Magic numbers, local variables and performance
Java “Magic numbers” anti-pattern http://refactoring.com/catalog/replaceMagicNumberWithSymbolicConstant.html 3 | 4/7/2019 | Magic numbers, local variables and performance
Test data database: AdventureWorks2012 table: Person.Address 4 | 4 | 4/7/2019 | Magic numbers, local variables and performance
“Magic numbers” in SQL –code /*original code*/ select addressid, AddressLine1, addressline2, city from [Person].[Address] where [StateProvinceID] = 9 go from [Person].[Address] where [StateProvinceID] = 119 /*refactored code*/ declare @state_california_USA int = 9 select addressid, AddressLine1, addressline2, city from [Person].[Address] where [StateProvinceID] = @state_california_USA go declare @state_gironde_FR int = 119 from [Person].[Address] where [StateProvinceID] = @state_gironde_FR 5 | 4/7/2019 | Magic numbers, local variables and performance
Original queries (IO stat, execution plans) (4564 row(s) affected) Table 'Address'. Scan count 1, logical reads 216, … (1 row(s) affected) logical reads 4, … 6 | 4/7/2019 | Magic numbers, local variables and performance
Original queries (Rows Estimated vs Actual) 7 | 4/7/2019 | Magic numbers, local variables and performance
“New” queries (IO stat, execution plans) (4564 row(s) affected) Table 'Address'. Scan count 1, logical reads 216, … (1 row(s) affected) 8 | 4/7/2019 | Magic numbers, local variables and performance
“New” queries (Rows Estimated vs Actual) 9 | 4/7/2019 | Magic numbers, local variables and performance
Statistics. DBCC SHOW_STATISTICS ('[Person].[Address]', IX_Address_StateProvinceID) 10 | 4/7/2019 | Magic numbers, local variables and performance
Statistics: Estimated Row Count 11 | 4/7/2019 | Magic numbers, local variables and performance
Statistics: 30% declare @i int = 179 select addressid, AddressLine1, addressline2, city from [Person].[Address] where [StateProvinceID] > @i go (62 row(s) affected) Table 'Address'. Scan count 1, logical reads 216, … 12 | 4/7/2019 | Magic numbers, local variables and performance
Statistics: 30% 13 | 4/7/2019 | Magic numbers, local variables and performance
Statistics: 30% declare @i int = 0 select addressid, AddressLine1, addressline2, city from [Person].[Address] where [StateProvinceID] > @i go 14 | 4/7/2019 | Magic numbers, local variables and performance
Execution plan – re-usage Parser – makes sure that the T-SQL query has a valid syntax, Output – Parse Tree Algebrizer – is responsible for objects and columns names verification. identifies all data types which are being processed for a given query. verify that GROUP BY and aggregate columns are placed in right place or not Output – Algebrized Tree Optimizer – execution plan creation Output – Execution Plan Execution – query execution 15 | 4/7/2019 | Magic numbers, local variables and performance
Execution plan – re-usage SELECT A.col5, SUM(C.col6) AS col6sum FROM TableA AS A INNER JOIN TableB AS B ON A.col1 = B.col1 INNER JOIN TableC AS C ON B.col2 = c.col2 WHERE A.col3 = constant1 AND B.col4 = constant2 GROUP BY A.col5; FROM (3! = 6 OR (4! / 2!) = 12 variants) : left-deep tree: JOIN( JOIN( JOIN(A, B), C), D). n! (6 tables – 720) bushy tree: JOIN(JOIN(A, B), JOIN(C, D)). (2n-2)!/(n-1)! (6 tables – 30,240) Realization (connection type): (Hash, merge, nested loop, star): 4 Access (index seek, index scan, table scan): 3 WHERE: AND : 2 GROUP BY: 2 ways (Stream (ordered) / Hash Match aggregate ) 6*4*2*2*3 = 288 OR 12 *4*2*2*3 = 576 16 | 4/7/2019 | Magic numbers, local variables and performance
Parameterization auto forced manual DBCC FREEPROCCACHE GO select addressid, AddressLine1, addressline2, city from [Person].[Address] where [StateProvinceID] = 9 declare @state_gironde_FR int = 119 from [Person].[Address] where [StateProvinceID] = @state_gironde_FR from [Person].[Address] where [StateProvinceID] = 119 declare @state_california_USA int = 9 where [StateProvinceID] = @state_california_USA auto forced manual 17 | 4/7/2019 | Magic numbers, local variables and performance
Parameterization: Adhoc queries SELECT usecounts, cacheobjtype, objtype, text FROM sys.dm_exec_cached_plans CROSS APPLY sys.dm_exec_sql_text(plan_handle) WHERE text like '%Address%' ORDER BY usecounts DESC; GO 18 | 4/7/2019 | Magic numbers, local variables and performance
Auto Parameterization select addressid, addressline1, addressline2, city from [Person].[Address] where [AddressID] = 9; go select addressid, addressline1, addressline2, city from [Person].[Address] where [AddressID] = 119; 19 | 4/7/2019 | Magic numbers, local variables and performance
Forced Parameterization alter database AdventureWorks2012 set parameterization forced; go select addressid, addressline1, addressline2, city from [Person].[Address] where [StateProvinceID] = 9; select addressid, addressline1, addressline2, city from [Person].[Address] where [StateProvinceID] = 119; alter database AdventureWorks2012 set parameterization simple; 20 | 4/7/2019 | Magic numbers, local variables and performance
Manual Parameterization (sp_executeSQL) declare @sql nvarchar(max) declare @parameters nvarchar(max) declare @i int set @sql = N'select addressid, addressline1, addressline2, city from [Person].[Address] where [StateProvinceID] = @i' set @parameters = N'@i int' set @i = 9 execute sp_executesql @sql, @parameters,@i set @i = 119 go 21 | 4/7/2019 | Magic numbers, local variables and performance
Manual Parameterization (procedures) create procedure dbo.get_address (@i int ) as begin select addressid, addressline1, addressline2, city from [Person].[Address] where [StateProvinceID] = @i end exec dbo.get_address 9 go exec dbo.get_address 119 22 | 4/7/2019 | Magic numbers, local variables and performance
SP side effect: non-effective plan 23 | 4/7/2019 | Magic numbers, local variables and performance
SP side effect: non-effective plan 24 | 4/7/2019 | Magic numbers, local variables and performance
Parameterization side effect: data conversion http://technet.microsoft.com/ru-ru/library/ms187745%28v=sql.110%29.aspx 25 | 4/7/2019 | Magic numbers, local variables and performance
Non-effective plan: how to avoid exec dbo.get_address 9 go exec sp_recompile 'dbo.get_address' exec dbo.get_address 119 exec dbo.get_address 9 go exec dbo.get_address 119 WITH RECOMPILE create procedure dbo.get_address (@i int) WITH RECOMPILE as begin select addressid, addressline1, addressline2, city from [Person].[Address] where [StateProvinceID] = @i end go Query hint: OPTION (RECOMPILE) 26 | 4/7/2019 | Magic numbers, local variables and performance
local variable: how to generate optimal plan declare @state_gironde_FR int = 119 select addressid, AddressLine1, addressline2, city from [Person].[Address] where [StateProvinceID] = @state_gironde_FR OPTION (recompile) go 27 | 4/7/2019 | Magic numbers, local variables and performance
No caching Option (Recompile) declare @state_gironde_FR int = 119 select addressid, AddressLine1, addressline2, city from [Person].[Address] where [StateProvinceID] = @state_gironde_FR OPTION (recompile) go select addressid, AddressLine1, addressline2, city from [Person].[Address] where [StateProvinceID] = 119 go No caching 28 | 4/7/2019 | Magic numbers, local variables and performance
Circle closed Option (recompile) Ad hoc queries Stored procedures Parameterization Stored procedures Option (recompile) 29 | 4/7/2019 | Magic numbers, local variables and performance
Side effect of the parameter sniffing create procedure dbo.get_address_sniffing (@i int ) as begin set @i = @i + 1 select addressid, addressline1, addressline2, city from [Person].[Address] where [StateProvinceID] = @i end Go DBCC FREEPROCCACHE exec dbo.get_address_sniffing 9 go 30 | 4/7/2019 | Magic numbers, local variables and performance
Side effect (parameter sniffing): how to avoid create procedure dbo.get_address_sniffing (@i int ) as begin set @i = @i + 1 select addressid, addressline1, addressline2, city from [Person].[Address] where [StateProvinceID] = @i OPTION (recompile) end Go DBCC FREEPROCCACHE exec dbo.get_address_sniffing 9 go 31 | 4/7/2019 | Magic numbers, local variables and performance
Option (Recompile): data filtering if object_id('dbo.get_address_by_filter','P') is not null drop procedure dbo.get_address_by_filter go create procedure dbo.get_address_by_filter ( @city nvarchar(30) = null ,@postalcode nvarchar(15) = null ,@stateprovinceid int = null ) as begin SELECT addressid, AddressLine1, addressline2, city FROM [AdventureWorks2012].[Person].[Address] where (city = @city or @city is null) and (postalcode = @postalcode or @postalcode is null) and (stateprovinceid = @stateprovinceid or @stateprovinceid is null) end 32 | 4/7/2019 | Magic numbers, local variables and performance
Option (Recompile): data filtering execute dbo.get_address_by_filter @stateprovinceid = 48 ,@city = N'Las Cruces' 33 | 4/7/2019 | Magic numbers, local variables and performance
Option (Recompile): data filtering if object_id('dbo.get_address_by_filter','P') is not null drop procedure dbo.get_address_by_filter go create procedure dbo.get_address_by_filter ( @city nvarchar(30) = null ,@postalcode nvarchar(15) = null ,@stateprovinceid int = null ) as begin SELECT addressid, AddressLine1, addressline2, city FROM [AdventureWorks2012].[Person].[Address] where (city = @city or @city is null) and (postalcode = @postalcode or @postalcode is null) and (stateprovinceid = @stateprovinceid or @stateprovinceid is null) option (recompile) end 34 | 4/7/2019 | Magic numbers, local variables and performance
Option (Recompile): data filtering execute dbo.get_address_by_filter @stateprovinceid = 48 ,@city = N'Las Cruces' 35 | 4/7/2019 | Magic numbers, local variables and performance
Option (Recompile): data ordering if object_id('dbo.get_address_by_order','P') is not null drop procedure dbo.get_address_by_order go create procedure dbo.get_address_by_order ( @orderby nvarchar(254) ) as begin SELECT top 100 addressid, AddressLine1, addressline2, city FROM [AdventureWorks2012].[Person].[Address] order by case @orderby when N'city' then city when N'postalcode' then postalcode when N'stateprovinceid' then stateprovinceid end 36 | 4/7/2019 | Magic numbers, local variables and performance
Option (Recompile): data ordering execute dbo.get_address_by_order N'stateprovinceid' 37 | 4/7/2019 | Magic numbers, local variables and performance
Option (Recompile): data ordering if object_id('dbo.get_address_by_order','P') is not null drop procedure dbo.get_address_by_order go create procedure dbo.get_address_by_order ( @orderby nvarchar(254) ) as begin SELECT top 100 addressid, AddressLine1, addressline2, city FROM [AdventureWorks2012].[Person].[Address] order by case @orderby when N'city' then city when N'postalcode' then postalcode when N'stateprovinceid' then stateprovinceid End Option (recompile) end 38 | 4/7/2019 | Magic numbers, local variables and performance
Option (Recompile): data ordering execute dbo.get_address_by_order N'stateprovinceid' SELECT top 100 addressid, AddressLine1, addressline2, city FROM [Person].[Address] order by stateprovinceid 39 | 4/7/2019 | Magic numbers, local variables and performance
Option (Recompile): data ordering execute dbo.get_address_by_order N‘city' order by case @orderby when N'city' then city when N'postalcode' then postalcode when N'stateprovinceid' then stateprovinceid End 40 | 4/7/2019 | Magic numbers, local variables and performance
Option (Recompile): data ordering if object_id('dbo.get_address_by_order','P') is not null drop procedure dbo.get_address_by_order go create procedure dbo.get_address_by_order ( @orderby nvarchar(254) ) as begin SELECT top 100 addressid, AddressLine1, addressline2, city FROM [AdventureWorks2012].[Person].[Address] order by case @orderby when N'city' then city when N'postalcode' then postalcode when N'stateprovinceid' then stateprovinceid else cast('' as sql_variant) end option (recompile) 41 | 4/7/2019 | Magic numbers, local variables and performance
“Magic numbers”, local variable and performance Q & A The end 42 | 4/7/2019 | Magic numbers, local variables and performance