Download presentation
Presentation is loading. Please wait.
1
T-SQL Performance Tuning
Jes Borland Premier Field Engineer, Data & AI
2
Goals Learn how SQL Server interprets queries
Learn strategies for making queries faster and less resource-intensive using T-SQL Learn about aggregations, window functions, subqueries, views, and functions to go beyond basic T-SQL
3
What is T-SQL? Transact SQL – Microsoft’s implementation of the ANSI standard Declarative language – you only tell SQL Server what you want, not how to do it
4
SELECT CustomerID, COUNT(SalesOrderID) AS CountOrders, SUM(TotalDue) AS TotalSales, AVG(TotalDue) AS AvgSales, MIN(TotalDue) AS MinOrder, MAX(TotalDue) AS MaxOrder FROM Sales.SalesOrderHeader SOH WHERE OrderDate >= '2014/01/01' AND OrderDate <= '2014/12/31' GROUP BY CustomerID ORDER BY COUNT(SalesOrderID) DESC;
5
Order of operations
6
Order of operations FROM WHERE GROUP BY HAVING SELECT ORDER BY
7
FROM FROM determines which tables or view the data is being retrieved from Only include tables or views you need data from Use aliases for easier recognition FROM dbo.Orders AS Ord Use primary key and foreign key relationships when creating your tables Indexes on FKs can reduce reads through join elimination
8
Demo - FROM Done
9
WHERE WHERE determines your predicates – what is the statement evaluated on? Equality and inequality options = <> > >= < <= BETWEEN IN The order of the fields in the WHERE clause compared to the order of the key columns in indexes matters! SARGability is an important consideration!
10
Index key columns and WHERE clause order
If the order of the predicates in the WHERE clause doesn’t match the order of the key columns in the index, SQL Server may still be able to use the index – but it may be a less-efficient scan, instead of a seek CREATE NONCLUSTERED INDEX IX_WhereClause ON dbo.WhereClauseDemo (OrderDate, DueDate, ShipDate); SELECT OrderDate FROM WhereClauseDemo WHERE ShipDate = ' '; Good place to mention the new showplan option “Estimated number of rows read”!
11
SARGability Searching a field that contains a value is a lot of work and can’t take advantage of indexes SELECT FirstName FROM Person WHERE FirstName LIKE '%Jen%’ This is a non-SARGable query A SARGable query can use indexes and is more efficient WHERE FirstName LIKE 'Jen%'
12
SARGability If you have a wildcard contains search, SQL Server will not use your index the way you intended it to Indexes on character fields (in particular) can hurt you if they are not being used Functions in the WHERE clause can cause issues too Options Computed column Full text search Range search
13
Demos – WHERE, WHERE – Key column order, SARGability
WHERE – Done WHERE Key column order – done SARGability – done
14
GROUP BY If it's in SELECT, and not aggregated, it's here
15
HAVING A predicate for the aggregations
Specifies a search condition based on a previously calculated aggregation
16
Demo – GROUP BY and HAVING
Done
17
SELECT Only include columns necessary for the operation you are performing SELECT *, while a shortcut, returns unnecessary data Using this in views or application code can introduce unwanted effects When selecting from multiple tables, reference the table’s alias you created in the FROM clause for easier recognition SELECT Ord.OrderID, Ord.OrderDate, OrdLin.ItemID, OrdLin.Quantity FROM dbo.Orders AS Ord JOIN dbo.OrderLines AS OrdLin ON OrdLin.OrderID = Ord.OrderID
18
Demo – SELECT Done
19
DISTINCT Specifies that only unique rows can appear in the result set
Removes duplicates based on column list results, not source table Provides uniqueness across set of selected columns Removes rows already operated on by WHERE, HAVING, and GROUP BY clauses Will likely inject a SORT operator into the query – which can add overhead to the query
20
TOP Lets you limit the number or percentage of rows returned by a query Works with ORDER BY clause to limit rows by sort order If ORDER BY list is not unique, results are not deterministic Modify ORDER BY list to ensure uniqueness, or use TOP WITH TIES Added to SELECT clause: SELECT TOP (N) | TOP (N) Percent With percent, number of rows rounded up SELECT TOP (N) WITH TIES Retrieve duplicates where applicable (nondeterministic)
21
Demo – DISTINCT and TOP Done
22
When is ORDER BY OK? Order isn't guaranteed unless this is used
Can declare ASC or DESC It requires a sort so be careful Use an indexed column
23
Joins
24
The Logical Join INNER JOIN OUTER JOIN Cross Join Self Join
CROSS APPLY OUTER APPLY
25
Understanding Inner Joins
Module 5: Querying Multiple Tables Course 10774A Understanding Inner Joins Returns rows matched between two input sources The comparison operator is typically equality (=) equi-join Matches rows based on attributes supplied in predicate ON clause in SQL-92 syntax Why filter in ON clause? Logical separation between filtering for purposes of join and filtering results in WHERE Typically no difference to query optimizer
26
Understanding Outer Joins
Module 5: Querying Multiple Tables Course 10774A Understanding Outer Joins Returns all rows from one table and any matching rows from second table Table ordering DOES matter here when written One table’s rows are “preserved” LEFT vs RIGHT refers to which table’s output will be reserved Additional rows added to results for non-matched rows NULLs added in place where attributes do not match Example: Return all customers and for those who have placed orders, return order information. Customers without matching orders will display NULL for order details. Consider explaining this as answering the "whether or not" question – all customers and their orders whether or not they have an order.
27
Understanding Cross Joins
Module 5: Querying Multiple Tables Course 10774A Understanding Cross Joins Combine each row from first table with each row from second table All possible combinations output Logical foundation for inner and outer joins Inner join starts with Cartesian product, adds filter Outer join takes Cartesian output, filtered, adds back non-matching rows (with NULL placeholders) Due to Cartesian product output, not typically a desired form of join Some useful exceptions: Table of numbers, generating data for testing
28
Understanding Self-Joins
Module 5: Querying Multiple Tables Course 10774A Understanding Self-Joins Why use self-joins? Compare rows in same table to each other Hierarchies and Organization charts are great examples Create two instances of same table in FROM clause At least one alias required Example: Return all employees and the name of the employee’s manager While only one alias is required, it is useful when demonstrating to alias both tables in the join.
29
Using the CROSS APPLY Operator
Module 12: Using Set Operators Course 10774A Using the CROSS APPLY Operator APPLY is a table operator used in the FROM clause Includes CROSS APPLY and OUTER APPLY Operates on two input tables, left and right Right table is often a derived table or a table-valued function Can be used with a table-valued function or a correlated subquery See APPLY in the REMARKS section of "FROM (Transact-SQL)" the Books Online: See also Remind students that use of "left" and "right" refers to the order of the tables as listed in the FROM clause, much like in a JOIN.
30
The Physical Join Nested loops Merge Hash
31
This is the execution plan of the INNER JOIN query
32
Nested Loops Best for small data sets
Outer (top) and inner (bottom) inputs Compare every row in inner loop to outer loop
33
Merge Both inputs must be sorted in the same order
Each row is compared
34
Hash Best for large data sets
Hash tables are built in memory – build and probe Values from probe compared to build
35
Demo – Joins Done
36
Views Named query stored in the database Great for security
Give a group or user access to a view, not the underlying table Can index for greater performance – “indexed view” or “materialized view”
37
Demo – Views Done
38
Writes INSERT – UPDATE – DELETE
39
INSERT INSERT INSERT INTO [...] SELECT [...] FROM [...]
Into one table at a time INSERT INTO [...] SELECT [...] FROM [...] Insert into an existing table from another table, temp table, or table variable SELECT [...] INTO [...] FROM [...] Creates new table from another table, temp table, or table variable
40
UPDATE Modify only existing data
Data can be filtered using a WHERE or JOIN clause
41
DELETE Delete specific rows from a given table
Data can be filtered using a WHERE or JOIN clause Use this method when you only want to remove certain rows – not everything in the table TRUNCATE is for emptying an entire table Deletion of each row is logged in database's transaction log
42
Writing good INSERT/UPDATE/DELETE statements
What slows them down? Too many rows at a time Too many nonclustered indexes on a table
43
Demo - INSERT - UPDATE - DELETE
Mostly done
44
Aggregations Performing calculations on the data What is the "cost"?
NULL values ignored (except COUNT) What is the "cost"? Aggregations require the server to do work. This can mean increased CPU usage, increased memory usage, and tempdb usage. AVG GROUPING_ID STDEVP CHECKSUM_AGG MAX STRING_AGG COUNT MIN VAR COUNT_BIG SUM VARP GROUPING STDEV AVG - Returns the average of the values in a group. Null values are ignored. CHECKSUM_AGG - Returns the checksum of the values in a group. Null values are ignored. CHECKSUM_AGG can be used to detect changes in a table. COUNT - Returns the number of items in a group. Always returns an int data type value. COUNT_BIG - Returns the number of items in a group. Always returns a bigint data type value. GROUPING - Indicates whether a specified column expression in a GROUP BY list is aggregated or not. Used to distinguish the null values that are returned by ROLLUP, CUBE or GROUPING SETS from standard null values. GROUPING_ID - Is a function that computes the level of grouping. MAX - Returns the maximum value in the expression. MIN - Returns the minimum value in the expression. STDEV - Returns the statistical standard deviation of all values in the specified expression. STDEVP - Returns the statistical standard deviation for the population for all values in the specified expression. SUM - Returns the sum of all the values, or only the DISTINCT values, in the expression. SUM can be used with numeric columns only. Null values are ignored. STRING_AGG - Concatenates the values of string expressions and places separator values between them. VAR - Returns the statistical variance of all values in the specified expression. VARP - Returns the statistical variance for the population for all values in the specified expression.
45
Demo - Aggregations Done
46
Window functions Aggregations over a partition (a window) of the result set Window functions can simplify queries that need to find running totals, moving averages, or gaps in data Ranking RANK, DENSE_RANK, NTILE, ROW_NUMBER Aggregate AVG, COUNT, MAX, MIN, SUM, STDEV, more Analytic FIRST_VALUE, LAST_VALUE, LEAD, LAG, more Ranking RANK, DENSE_RANK, NTILE, ROW_NUMBER Aggregate AVG, COUNT, MAX, MIN, SUM, STDEV, more Analytic FIRST_VALUE, LAST_VALUE, LEAD, LAG, more
47
Syntax SELECT Column1, Column2, RANK() OVER (PARTITION BY Column1 ORDER BY Column2 ASC) FROM Table1 WHERE Column1 IS NOT NULL;
48
Module 13: Using Window Ranking, Offset and Aggregate Functions
Course 10774A The OVER Clause OVER defines a window, or set of rows to be used by a window function, including any ordering The OVER clause restricts the set of rows to those with the same values in the partitioning elements By itself, OVER() is unrestricted and includes all rows Multiple OVER clauses can be used in a single query, each with its own partitioning and ordering, if needed For example, SUM(<col>) OVER () means to calculate the aggregate (SUM) using the underlying query's result set (all rows). SUM(<col>) OVER (PARTITION BY <col>) means to calculate the aggregate once for each window of rows restricted to only those rows that have the same value in <col> as in the current row.
49
Module 13: Using Window Ranking, Offset and Aggregate Functions
Course 10774A Partition By Partitioning applies a windowing function to a set to rows in a result set that share the same columns in the PARTITION BY clause Without a PARTITION BY clause defined, OVER() creates a single partition of all rows Don't take the comparison too far, but PARTITION is conceptually similar to a GROUP BY, even if the mechanisms are very different.
50
Demo – Window Functions
Done
51
Subqueries Nested queries – in SELECT, FROM, or WHERE
Results of inner passed to outer Dependent? Self-contained - not dependent on outer query Correlated - dependent on outer query Return values Scalar - returns single value to outer query Multi-valued - returns multiple values - use with IN Table-valued
52
Self-contained subquery
Write a query that can be in the SELECT, FROM, or WHERE clause Can reference one of the tables or views in the outer query, or different tables or views May return scalar value or multiple values
53
Correlated Subqueries
Module 10: Using Subqueries Course 10774A Correlated Subqueries Correlated subqueries refer to elements of tables used in outer query Dependent on outer query, cannot be executed separately Harder to test than self-contained subqueries Behaves as if inner query is executed once per outer row May return scalar value or multiple values Question: Why can't a correlated subquery be executed separately from the outer query? The subquery depends on input from the outer query for its values.
54
Writing Scalar Subqueries
Module 10: Using Subqueries Course 10774A Writing Scalar Subqueries Scalar subquery returns single value to outer query Can be used anywhere single-valued expression can be used: SELECT, WHERE, etc. If inner query returns an empty set, result is converted to NULL The example returns details about the most recent order. This is the error returned if the inner query is not scalar and the outer is written to expect a single value: Msg 512, Level 16, State 1, Line 1 Subquery returned more than 1 value. This is not permitted when the subquery follows =, !=, <, <= , >, >= or when the subquery is used as an expression.
55
Writing Multi-Valued Subqueries
Module 10: Using Subqueries Course 10774A Writing Multi-Valued Subqueries Multi-valued subquery returns multiple values as a single column set to the outer query Used with IN predicate If any value in the subquery result matches IN predicate expression, the predicate returns TRUE May also be expressed as a JOIN (test both for performance) The example returns information about orders placed by customers in Mexico. This may be rewritten as a JOIN: SELECT c.custid, o.orderid FROM Sales.Customers AS c JOIN Sales.Orders AS o ON c.custid = o.custid WHERE c.country = 'Mexico‘ Point out to the students that sometimes it’s easier to write and test a query one piece at a time, in which case a subquery may be more accessible.
56
Demo – Subqueries Done
57
Derived table May be used in place of a temp tables, if you don’t need to reference it more than once A SELECT statement, referenced in the FROM clause Query-scoped Can get ugly if nested
58
Demo - Derived table Done
59
CTEs A temporary result set
Can define multiple CTEs and reference in one final SELECT Great for recursion ;WITH CTEName (Optional Defined Fields) AS ( SELECT statement ) SELECT * FROM CTEName
60
CTE versus Temporary Tables
Temporary tables inherit no indexes from base tables, causing table scans CTEs use the raw tables (reducing processing time) When using a temporary table, the table has no index on it, and therefore SSE will complete a table scan operation on it when executing the second part. In contrast, CTEs use the raw tables. There is no creation of a temporary table, which uses up processing time, and also existing indexes could be used in building up the query as well rather than a table scan. The CTE is built up using the WITH keyword, which defines the name of the CTE you’ll be returning. The columns returned within the CTE will take the data types placed into it from the SELECT statement within the brackets. Of course, the number of columns within the CTE has to be the same as the table defined within the brackets. This table is built up, returned, and passed immediately into the following SELECT statement outside the WITH block where the rows of data can then be processed as required. Therefore, the rows returned between the brackets could be seen as a temporary table that is used by the statement outside the brackets. Explicitly materializing a CTE (or view or sub-select) result does not always yield better performance. First, we must consider the cost of creating and writing the temp table. If the cost of computing the CTE is not too great, it may be cheaper simply to compute the CTE result multiple times. Second, in some cases, the query optimizer may be able to choose a better plan and avoid computing the entire CTE result. For example, suppose that we only want to compute the number of orders for a single employee: INT = 268; WITH Sales_CTE (SalesPersonID, NumberOfOrders, MaxDate) AS ( SELECT SalesPersonID, COUNT(*), MAX(OrderDate) FROM Sales.SalesOrderHeader GROUP BY SalesPersonID ) SELECT E.EmployeeID, OS.NumberOfOrders, OS.MaxDate, E.ManagerID, OM.NumberOfOrders, OM.MaxDate FROM HumanResources.Employee AS E JOIN Sales_CTE AS OS ON E.EmployeeID = OS.SalesPersonID LEFT OUTER JOIN Sales_CTE AS OM ON E.ManagerID = OM.SalesPersonID WHERE E.EmployeeID This query yields a different plan from the original query: |--Nested Loops(Left Outer Join, OUTER REFERENCES:([E].[ManagerID])) |--Nested Loops(Inner Join) | |--Clustered Index Seek(OBJECT:([HumanResources].[Employee].[PK_Employee_EmployeeID] AS [E]), ORDERED FORWARD) | |--Compute Scalar(DEFINE:([Expr1005]=CONVERT_IMPLICIT(int,[Expr1021],0))) | |--Stream Aggregate(DEFINE:([Expr1021]=Count(*), [Expr1006]=MAX([Sales].[SalesOrderHeader].[OrderDate]))) | |--Clustered Index Scan(OBJECT:([Sales].[SalesOrderHeader].[PK_SalesOrderHeader_SalesOrderID]), |--Compute Scalar(DEFINE:([Expr1010]=[Expr1010], [Expr1011]=[Expr1011])) |--Compute Scalar(DEFINE:([Expr1010]=CONVERT_IMPLICIT(int,[Expr1022],0))) |--Stream Aggregate(DEFINE:([Expr1022]=Count(*), [Expr1011]=MAX([Sales].[SalesOrderHeader].[OrderDate]))) |--Clustered Index Scan(OBJECT:([Sales].[SalesOrderHeader].[PK_SalesOrderHeader_SalesOrderID]), WHERE:([E].[ManagerID]=[Sales].[SalesOrderHeader].[SalesPersonID])) While the original plan computed the number of orders and the most recent order date for all employees, this plan only computes this information for a single employee and for that employee's manager. Observe the WHERE predicates on the clustered index scans of the SalesOrderHeader table. Moreover, notice that this plan uses scalar stream aggregates instead of the hash aggregates in the original plan. Finally, in this example, the optimizer chose scans, but if the tables involved were larger and the predicates were more selective, it would have chosen index seeks to avoid scanning the entire table.
61
CTE Guidelines A CTE must be followed by a single SELECT, INSERT, UPDATE, or DELETE statement Multiple CTE query definitions can be defined in a nonrecursive CTE A CTE can reference itself and previously defined CTEs in the same WITH clause More than one WITH clause is not allowed
62
Recursive CTE Guidelines
Must contain at least one anchor member and one recursive member Anchor members must be combined by one of these set operators: UNION ALL, UNION, INTERSECT, or EXCEPT The number of columns in the anchor and recursive members must be the same. The data type of a column in the recursive member must be the same as the data type of the corresponding column in the anchor member The FROM clause of a recursive member must refer only one time to the CTE expression_name Certain items are not allowed in the CTE_query_definition of a recursive member All columns returned by the recursive CTE are nullable regardless of the nullability of the columns returned by the participating SELECT statements. An incorrectly composed recursive CTE may cause an infinite loop. Use MAXRECURSION to limit the number of recursion levels allowed. A view that contains a recursive common table expression cannot be used to update data Cursors may be defined on queries using CTEs. Tables on remote servers may be referenced in the CTE. The following guidelines apply to defining a recursive common table expression: The recursive CTE definition must contain at least two CTE query definitions, an anchor member and a recursive member. Multiple anchor members and recursive members can be defined; however, all anchor member query definitions must be put before the first recursive member definition. All CTE query definitions are anchor members unless they reference the CTE itself. Anchor members must be combined by one of these set operators: UNION ALL, UNION, INTERSECT, or EXCEPT. UNION ALL is the only set operator allowed between the last anchor member and first recursive member, and when combining multiple recursive members. The number of columns in the anchor and recursive members must be the same. The data type of a column in the recursive member must be the same as the data type of the corresponding column in the anchor member. The FROM clause of a recursive member must refer only one time to the CTE expression_name. The following items are not allowed in the CTE_query_definition of a recursive member: SELECT DISTINCT GROUP BY HAVING Scalar aggregation TOP LEFT, RIGHT, OUTER JOIN (INNER JOIN is allowed) Subqueries A hint applied to a recursive reference to a CTE inside a CTE_query_definition.
63
Demo – CTEs Done
64
Temp tables A temporary table construct created in the tempdb database
Local – prefix with # - session-scoped A local temporary table created in a stored procedure is dropped automatically when the stored procedure is finished All other local temporary tables are dropped automatically at the end of the current session Global – prefix with ## - instance-scoped Global temporary tables are automatically dropped when the session that created the table ends and all other tasks have stopped referencing them Issue SELECT, INSERT, UPDATE, DELETE against them Create indexes against them
65
Table variables Primarily used for temporary storage of a set of rows returned as the result set of a table-valued function A table variable behaves like a local variable. It has a well-defined scope. Automatically cleaned up at the end of the function, stored procedure, or batch in which they are defined.
66
Table variable limitations
No statistics, will not trigger recompiles If more than 100 rows, may want to use a temp table If joining to other tables, use RECOMPILE hint to get correct cardinality No cost-based optimization Temp tables preferred for queries with joins, parallelism decisions, and index selection choices Queries that modify table variables do not generate parallel query execution plans Indexes can’t be created explicitly on table variables, and no statistics are kept on table variables
67
Demo – Temp objects
68
What are functions? Encapsulated T-SQL Great for code re-use
Can have a huge performance impact when they're called from a SELECT or WHERE clause
69
Types of User Defined Functions
Returns a single value of a single data type Scalar Returns a resultset from a single SELECT statement Inline Table Valued Returns a resultset using a defined table variable, allowing more complex T-SQL Multi-statement Table Valued
70
Scalar Functions Great for code encapsulation
9: Designing and Implementing User-Defined Functions Scalar Functions Great for code encapsulation Return a single data value of the data type defined in the function Can return any data type except text, ntext, image, timestamp, rowversion, cursor, or table Can be called in a SELECT statement or from an EXECUTE command You can pass column values into the function in the SELECT statement Mention that user-defined scalar functions return a single data value of the type defined in the RETURNS clause. Finally mention that the return type can be any data type except rowversion, cursor and table. Mention that scalar functions that are created in managed code have slightly different limitations on returned data types. Do not, however, dwell on managed code at this point as it is covered in module 12.
71
Calling the function Query is executed
This slide is to show how the function is called from a SELECT statement, and show the results of the function in the column
72
What is the performance impact?
Where is the function? This slide shows the execution plan, which makes no reference to the function, and the executions of the function as observed by capturing the sp_statement_completed event in an Extended Events session. XE shows us the executions
73
Inline Table-Valued Functions
Module 11: Using Table Expressions Course 10774A Inline Table-Valued Functions Can be thought of as a parameterized view Returns a result set Declare return type as TABLE Define inline SELECT statement following RETURN A single SELECT statement is allowed in the UDF body Often the best option for defining UDFs
74
Writing Queries That Use Inline Table-Valued Functions
Module 11: Using Table Expressions Course 10774A Writing Queries That Use Inline Table-Valued Functions Table-valued functions (TVFs) are named table expressions with definitions stored in a database TVFs return a virtual table to the calling query Unlike views, TVFs support input parameters
75
Retrieving from Inline Table-Valued Functions
Module 11: Using Table Expressions Course 10774A Retrieving from Inline Table-Valued Functions SELECT from function Use two-part name Pass in parameters USE CROSS/OUTER APPLY to pass in values from columns in a table
76
Calling the function Query is executed
77
What is the performance impact?
Where is the function? XE shows us the executions
78
Multistatement Table-Valued Functions
9: Designing and Implementing User-Defined Functions Multistatement Table-Valued Functions Definition of returned table must be supplied Function body is enclosed by BEGIN and END Allows for more complex T-SQL logic Table variable is populated within function body and then returned This DOES create an object in tempdb for each call to the function!!
79
Calling the function Query is executed
80
What is the performance impact?
XE shows us the executions
81
MSTVFs and row estimates
MSTVFs have a fixed cardinality guess of “100” in SQL Server 2014 and 2016, and “1” for earlier versions We have a MSTVF Table Scan that has a fixed estimate of 100 rows. But for this example, there are 527,592 flowing through this MSTVF Table Scan as seen in Live Query Statistics via the “ of 100” actual of estimated – so our fixed estimate is significantly skewed. For the Nested Loops operation, we’re still assuming only 100 rows are flowing through the outer reference. Given the high number of rows actually being returned by the MSTVF, we’re likely better off with a different join algorithm altogether. For the Hash Match operation, notice the small warning symbol, which in this case is indicating a spill to disk.
82
SQL Server 2017 introduces interleaved execution
Notice that the MSTVF table scan now reflects an accurate cardinality estimate. Also notice the re-ordering of this table scan and the other operations. And regarding join algorithms, we have switched from a Nested Loop operation to a Hash Match operation instead, which is more optimal given the large number of rows involved. Also notice that we no longer have spill-warnings, as we’re granting more memory based on the true row count flowing from the MSTVF table scan.
83
Types of User Defined Functions
Returns a single value of a single data type Scalar Returns a resultset from a single SELECT statement Inline Table Valued Returns a resultset using a defined table variable, allowing more complex T-SQL Multi-statement Table Valued
84
When to use each function type
When you need the same logic applied to every row in a result set Scalar Use one SELECT statement to return a table result set Inline Table Valued Use more complex logic to return a table result set Multi-statement Table Valued
85
Performance Impact of User Defined Functions
9: Designing and Implementing User-Defined Functions Performance Impact of User Defined Functions Inline Table Valued Functions Code is often rewritten by the optimizer to be a JOIN Often results in the best performance choice of all 3 types of UDFs Scalar and Multistatement TVF SQL Server does not re-write the query to be a JOIN like it does with an in-line TVF Very common cause of performance problems Multi-statement TVFs create a very heavy load on tempdb Each function call creates a table variable in tempdb With scalar user-defined functions, the code that defines the function is not incorporated directly into the surrounding query. Performance problems with these functions are well-known in the SQL Server community. Particular impacts are caused when the functions are executed for each row in a table. CROSS APPLY is used to call a table-valued function for each row in a table.
86
Demo - Functions Done
87
Module 16: Executing Stored Procedures
Course 10774A Dynamic SQL Dynamic SQL is T-SQL code assembled and executed at run time Provides flexibility for administrative and programming tasks Two methods for dynamically executing SQL statements: EXECUTE/EXEC command can accept a string as input in parentheses. No parameters may be passed in. System stored procedure sp_executesql (preferred) supports parameters. Breaks permission chaining Permissions on the base table are required Beware of risks from unvalidated inputs in dynamic SQL! Otherwise SQL injection attacks may occur See the section "Using EXECUTE with a Character String" in Books Online: See "SQL Injection" in Books Online:
88
Dynamic SQL using EXECUTE
Accepts string to be executed Does not allow for parameterization This can open more opportunities for SQL Injection attacks Generally a less ideal option than using sp_executesql
89
Dynamic SQL using sp_executesql
Module 16: Executing Stored Procedures Course 10774A Dynamic SQL using sp_executesql Accepts string as code to be run Supports input, output parameters for query Allows parameterized code while minimizing risk of SQL injection Can perform better than EXECUTE due to query plan reuse See Books Online for discussions of query plan reuse and more coverage of sp_executesql:
90
When to use dynamic SQL Handling multiple OR clauses in a WHERE statement Example: a stored procedure supporting a dynamic search screen in an application Dealing with parameter sniffing Could lead to plan cache bloat Which can be mitigated with the Optimize for ad hoc workloads server property
91
Simple --Simple query - no parameters SELECT ProductID, LocationID, Shelf, Bin, Quantity FROM Production.ProductInventory --Rewritten as dynamic SQL nvarchar(1000) = N'SELECT ProductID, LocationID, Shelf, Bin, Quantity FROM Production.ProductInventory' EXECUTE It’s OK to use EXECUTE () here – there are no parameters, so don’t worry about ad hoc optimization, or injection
92
With input parameters --Declare external variables nvarchar(max) --The variable that will be the SQL statement nvarchar(1000) --Used to build string, not used in sp_executesql INT --The variable for the WHERE clause = 'ProductID, LocationID, Shelf, Bin, Quantity' --Set external variables = Assigning a value to that variable = N'SELECT + ' FROM Production.ProductInventory WHERE ProductID --Execute sp_execute SQL, passing in: --1. The variable name of the SQL statement --2. A string containing the name and data type of the variable for the WHERE clause --3. The values for the WHERE clause EXEC
93
With output parameters
nvarchar(max) --The variable that will be the SQL statement INT --The variable for the WHERE clause INT --The output variable --Set external variables = Assigning a value to that variable = = SUM(Quantity) FROM Production.ProductInventory WHERE ProductID GROUP BY ProductID' --Execute EXECUTE INT = OUTPUT;
94
Demo – Dynamic SQL Dynamic SQL.sql
Similar presentations
© 2025 SlidePlayer.com. Inc.
All rights reserved.