You signed in with another tab or window. Reload to refresh your session.You signed out in another tab or window. Reload to refresh your session.You switched accounts on another tab or window. Reload to refresh your session.Dismiss alert
Copy file name to clipboardExpand all lines: docs/includes/entra-id-tutorial.md
+1-1Lines changed: 1 addition & 1 deletion
Display the source diff
Display the rich diff
Original file line number
Diff line number
Diff line change
@@ -103,7 +103,7 @@ Or,
103
103
104
104
1. For the **Method of certificate creation**, use **Generate**.
105
105
106
-
1. Add a certificate name and subject.
106
+
1. Add a certificate name and subject. The certificate name must be unique. A certificate name that matches an existing certificate causes an error when the login is created.
107
107
108
108
1. The recommended validity period is at most 12 months. The rest of the values can be left as default.
@@ -235,6 +235,19 @@ LAQ is disabled for the database if the percentage of the potentially wasted wor
235
235
236
236
If the wasted work and the number of restarted statements fall below their respective thresholds, LAQ is re-enabled for the database.
237
237
238
+
#### LAQ limitations
239
+
240
+
Lock after qualification might not be used in the following scenarios:
241
+
242
+
- When disabled by [LAQ heuristics](#laq-heuristics).
243
+
- When conflicting locking hints, such as `UPDLOCK`, `READCOMMITTEDLOCK`, `XLOCK`, or `HOLDLOCK` are used.
244
+
- When the transaction isolation level is other than `READ COMMITTED`, or when the `READ_COMMITTED_SNAPSHOT` database option is disabled.
245
+
- When the table being modified has a columnstore index.
246
+
- When the DML statement includes variable assignment.
247
+
- When the DML statement has an `OUTPUT` clause.
248
+
- When the DML statement uses more than one index seek or scan operator to read the rows being modified.
249
+
- In `MERGE` statements.
250
+
238
251
### <aid="behavior"></a> Query behavior changes with optimized locking and RCSI
239
252
240
253
Concurrent workloads under read committed snapshot isolation (RCSI) that rely on strict execution order of transactions might experience differences in query behavior when optimized locking is enabled.
@@ -304,7 +317,7 @@ The following improvements help you monitor and troubleshoot blocking and deadlo
304
317
- Under each resource in the deadlock report `<resource-list>`, each `<xactlock>` element reports the underlying resources and specific information for locks of each member of a deadlock. For more information and an example, see [Optimized locking and deadlocks](../sql-server-deadlocks-guide.md#optimized-locking-and-deadlocks).
305
318
- Extended events
306
319
- The `lock_after_qual_stmt_abort` event fires when a statement is internally aborted and restarted because of a conflict with another transaction. For more information, see [Lock after qualification (LAQ)](#lock-after-qualification-laq).
307
-
- In [!INCLUDE [sssql25-md](../../includes/sssql25-md.md)], the `locking_stats` event fires for every database every several minutes and provides aggregate locking statistics for the time interval, such as the number of lock escalations, whether TID locking and LAQ components of optimized locking are enabled, and the number of queries that were ineligible for LAQ for various reasons. This event fires even if optimized locking is disabled.
320
+
- In [!INCLUDE [sssql25-md](../../includes/sssql25-md.md)], the `locking_stats` event fires for every database every several minutes and provides aggregate locking statistics for the time interval, such as the number of lock escalations, whether TID locking and LAQ components of optimized locking are enabled, and the number of queries where LAQ wasn't used for various reasons. This event fires even if optimized locking is disabled.
Copy file name to clipboardExpand all lines: docs/relational-databases/security/authentication-access/azure-ad-authentication-sql-server-setup-tutorial.md
Copy file name to clipboardExpand all lines: docs/relational-databases/statistics/statistics.md
+68-66Lines changed: 68 additions & 66 deletions
Display the source diff
Display the rich diff
Original file line number
Diff line number
Diff line change
@@ -4,7 +4,7 @@ description: The Query Optimizer uses statistics to create query plans that impr
4
4
author: WilliamDAssafMSFT
5
5
ms.author: wiassaf
6
6
ms.reviewer: derekw, randolphwest
7
-
ms.date: 12/17/2024
7
+
ms.date: 07/07/2025
8
8
ms.service: sql
9
9
ms.subservice: performance
10
10
ms.topic: conceptual
@@ -206,6 +206,8 @@ In [!INCLUDE [ssNoVersion](../../includes/ssnoversion-md.md)] prior to [!INCLUDE
206
206
207
207
Starting with [!INCLUDE [sssql22-md](../../includes/sssql22-md.md)], the auto drop option is enabled by default on all new and migrated databases. The `AUTO_DROP` property allows the creation of statistics objects in a mode such that a subsequent schema change *isn't* blocked by the statistic object, but instead the statistics are dropped as necessary. In this way, manually created statistics with auto drop enabled behave like auto-created statistics.
208
208
209
+
In [!INCLUDE [ssazure-sqldb](../../includes/ssazure-sqldb.md)], [!INCLUDE [ssazuremi-md](../../includes/ssazuremi-md.md)], and [!INCLUDE [sssql22-md](../../includes/sssql22-md.md)] and later versions, automatically created statistics always behave as though the [AUTO_DROP](../../relational-databases/statistics/statistics.md#auto_drop-option) has been set.
210
+
209
211
> [!NOTE]
210
212
> Trying to set or unset the auto drop property on auto-created statistics can raise errors. Auto-created statistics always uses auto drop. Some backups, when restored, can have this property set incorrectly until the next time the statistics object is updated (manually or automatically). However, auto-created statistics always behave like auto drop statistics. When restoring a database to [!INCLUDE [sssql22-md](../../includes/sssql22-md.md)] from a previous version, it's recommended to execute `sp_updatestats` on the database, setting the proper metadata for the statistics auto drop feature.
211
213
@@ -261,8 +263,8 @@ The Query Optimizer already creates statistics in the following ways:
261
263
262
264
1. The Query Optimizer creates statistics for indexes on tables or views when the index is created. These statistics are created on the key columns of the index. If the index is a filtered index, the Query Optimizer creates filtered statistics on the same subset of rows specified for the filtered index. For more information about filtered indexes, see [Create filtered indexes](../indexes/create-filtered-indexes.md) and [CREATE INDEX](../../t-sql/statements/create-index-transact-sql.md).
263
265
264
-
> [!NOTE]
265
-
> Starting with [!INCLUDE [ssSQL14](../../includes/sssql14-md.md)], statistics aren't created by scanning all rows in the table when a partitioned index is created or rebuilt. Instead, the Query Optimizer uses the default sampling algorithm to generate statistics. After upgrading a database with partitioned indexes, you might notice a difference in the histogram data for these indexes. This change in behavior might not affect query performance. To obtain statistics on partitioned indexes by scanning all the rows in the table, use `CREATE STATISTICS` or `UPDATE STATISTICS` with the `FULLSCAN` clause.
266
+
> [!NOTE]
267
+
> In [!INCLUDE [ssSQL14](../../includes/sssql14-md.md)] and later versions, statistics aren't created by scanning all rows in the table when a partitioned index is created or rebuilt. Instead, the Query Optimizer uses the default sampling algorithm to generate statistics. After upgrading a database with partitioned indexes, you might notice a difference in the histogram data for these indexes. This change in behavior might not affect query performance. To obtain statistics on partitioned indexes by scanning all the rows in the table, use `CREATE STATISTICS` or `UPDATE STATISTICS` with the `FULLSCAN` clause.
266
268
267
269
1. The Query Optimizer creates statistics for single columns in query predicates when [AUTO_CREATE_STATISTICS](../../t-sql/statements/alter-database-transact-sql-set-options.md#auto_create_statistics) is on.
268
270
@@ -442,69 +444,69 @@ To improve the cardinality estimates for variables and functions, follow these g
442
444
443
445
- If a stored procedure contains a query that uses a passed-in parameter, avoid changing the parameter value within the stored procedure before using it in the query. The cardinality estimates for the query are based on the passed-in parameter value and not the updated value. To avoid changing the parameter value, you can rewrite the query to use two stored procedures.
444
446
445
-
For example, the following stored procedure `Sales.GetRecentSales` changes the value of the parameter `@date` when `@date` is `NULL`.
446
-
447
-
```sql
448
-
USE AdventureWorks2022;
449
-
GO
450
-
451
-
IF OBJECT_ID('Sales.GetRecentSales', 'P') IS NOT NULL
452
-
DROP PROCEDURE Sales.GetRecentSales;
453
-
GO
454
-
455
-
CREATE PROCEDURE Sales.GetRecentSales
456
-
@date DATETIME
457
-
AS
458
-
BEGIN
459
-
IF @date IS NULL
460
-
SET @date= DATEADD(MONTH, -3,
461
-
(SELECTMAX(ORDERDATE)
462
-
FROMSales.SalesOrderHeader));
463
-
SELECT*
464
-
FROMSales.SalesOrderHeaderAS h, Sales.SalesOrderDetailAS d
465
-
WHEREh.SalesOrderID=d.SalesOrderID
466
-
ANDh.OrderDate> @date;
467
-
END
468
-
GO
469
-
```
470
-
471
-
If the first call to the stored procedure `Sales.GetRecentSales` passes a `NULL` for the `@date` parameter, the Query Optimizer compiles the stored procedure with the cardinality estimate for `@date = NULL` even though the query predicate isn't called with `@date = NULL`. This cardinality estimate might be significantly different than the number of rows in the actual query result. As a result, the Query Optimizer might choose a suboptimal query plan. To help avoid this, you can rewrite the stored procedure into two procedures as follows:
472
-
473
-
```sql
474
-
USE AdventureWorks2022;
475
-
GO
476
-
477
-
IF OBJECT_ID('Sales.GetNullRecentSales', 'P') IS NOT NULL
478
-
DROP PROCEDURE Sales.GetNullRecentSales;
479
-
GO
480
-
481
-
CREATE PROCEDURE Sales.GetNullRecentSales
482
-
@date DATETIME
483
-
AS
484
-
BEGIN
485
-
IF @date IS NULL
486
-
SET @date = DATEADD(MONTH, -3,
487
-
(SELECT MAX(ORDERDATE)
488
-
FROM Sales.SalesOrderHeader));
489
-
EXECUTE Sales.GetNonNullRecentSales @date;
490
-
END
491
-
GO
492
-
493
-
IF OBJECT_ID('Sales.GetNonNullRecentSales', 'P') IS NOT NULL
494
-
DROP PROCEDURE Sales.GetNonNullRecentSales;
495
-
GO
496
-
497
-
CREATE PROCEDURE Sales.GetNonNullRecentSales
498
-
@date DATETIME
499
-
AS
500
-
BEGIN
501
-
SELECT *
502
-
FROM Sales.SalesOrderHeader AS h, Sales.SalesOrderDetail AS d
503
-
WHERE h.SalesOrderID = d.SalesOrderID
504
-
AND h.OrderDate > @date;
505
-
END
506
-
GO
507
-
```
447
+
For example, the following stored procedure `Sales.GetRecentSales` changes the value of the parameter `@date` when `@date` is `NULL`.
448
+
449
+
```sql
450
+
USE AdventureWorks2022;
451
+
GO
452
+
453
+
IF OBJECT_ID('Sales.GetRecentSales', 'P') IS NOT NULL
454
+
DROP PROCEDURE Sales.GetRecentSales;
455
+
GO
456
+
457
+
CREATE PROCEDURE Sales.GetRecentSales
458
+
@date DATETIME
459
+
AS
460
+
BEGIN
461
+
IF @date IS NULL
462
+
SET @date= DATEADD(MONTH, -3,
463
+
(SELECTMAX(ORDERDATE)
464
+
FROMSales.SalesOrderHeader));
465
+
SELECT*
466
+
FROMSales.SalesOrderHeaderAS h, Sales.SalesOrderDetailAS d
467
+
WHEREh.SalesOrderID=d.SalesOrderID
468
+
ANDh.OrderDate> @date;
469
+
END
470
+
GO
471
+
```
472
+
473
+
If the first call to the stored procedure `Sales.GetRecentSales` passes a `NULL` for the `@date` parameter, the Query Optimizer compiles the stored procedure with the cardinality estimate for `@date = NULL` even though the query predicate isn't called with `@date = NULL`. This cardinality estimate might be significantly different than the number of rows in the actual query result. As a result, the Query Optimizer might choose a suboptimal query plan. To help avoid this, you can rewrite the stored procedure into two procedures as follows:
474
+
475
+
```sql
476
+
USE AdventureWorks2022;
477
+
GO
478
+
479
+
IF OBJECT_ID('Sales.GetNullRecentSales', 'P') IS NOT NULL
480
+
DROP PROCEDURE Sales.GetNullRecentSales;
481
+
GO
482
+
483
+
CREATE PROCEDURE Sales.GetNullRecentSales
484
+
@date DATETIME
485
+
AS
486
+
BEGIN
487
+
IF @date IS NULL
488
+
SET @date= DATEADD(MONTH, -3,
489
+
(SELECTMAX(ORDERDATE)
490
+
FROMSales.SalesOrderHeader));
491
+
EXECUTE Sales.GetNonNullRecentSales @date;
492
+
END
493
+
GO
494
+
495
+
IF OBJECT_ID('Sales.GetNonNullRecentSales', 'P') IS NOT NULL
496
+
DROP PROCEDURE Sales.GetNonNullRecentSales;
497
+
GO
498
+
499
+
CREATE PROCEDURE Sales.GetNonNullRecentSales
500
+
@date DATETIME
501
+
AS
502
+
BEGIN
503
+
SELECT*
504
+
FROMSales.SalesOrderHeaderAS h, Sales.SalesOrderDetailAS d
0 commit comments