我有一个要优化的 SQL 查询:
DECLARE @Id UNIQUEIDENTIFIER = 'cec094e5-b312-4b13-997a-c91a8c662962'
SELECT
Id,
MIN(SomeTimestamp),
MAX(SomeInt)
FROM dbo.MyTable
WHERE Id = @Id
AND SomeBit = 1
GROUP BY Id
Run Code Online (Sandbox Code Playgroud)
MyTable
有两个索引:
CREATE NONCLUSTERED INDEX IX_MyTable_SomeTimestamp_Includes
ON dbo.MyTable (SomeTimestamp ASC)
INCLUDE(Id, SomeInt)
CREATE NONCLUSTERED INDEX IX_MyTable_Id_SomeBit_Includes
ON dbo.MyTable (Id, SomeBit)
INCLUDE (TotallyUnrelatedTimestamp)
Run Code Online (Sandbox Code Playgroud)
当我完全按照上面写的方式执行查询时,SQL Server 扫描第一个索引,导致 189,703 次逻辑读取和 2-3 秒的持续时间。
当我内联@Id
变量并再次执行查询时,SQL Server 寻找第二个索引,导致只有 104 次逻辑读取和 0.001 秒的持续时间(基本上是即时的)。
我需要变量,但我希望 SQL 使用好的计划。作为临时解决方案,我在查询上放置了索引提示,查询基本上是即时的。但是,我尽量避免使用索引提示。我通常假设如果查询优化器无法完成它的工作,那么我可以做(或停止做)一些事情来帮助它,而无需明确告诉它该做什么。
那么,当我内联变量时,为什么 SQL Server 会提出更好的计划?
我想将一张表合并到另一张表中。我需要在我的 WHEN MATCHED 子句中应用条件逻辑,理想情况下这样做:
MERGE INTO ATable AS a
USING BTable AS b
ON a.ID = b.ID
WHEN NOT MATCHED THEN
-- Do insert
WHEN MATCHED AND b.NeedsAdjustment = 1 THEN
UPDATE SET
Col1 = b.Col1 + b.Adjustment
,Col2 = b.Col2 + b.Adjustment
,Col3 = b.Col3 + b.Adjustment
WHEN MATCHED THEN -- Default case (b.NeedsAdjustment <> 1)
UPDATE SET
Col1 = b.Col1
,Col2 = b.Col2
,Col3 = b.Col3
Run Code Online (Sandbox Code Playgroud)
这不是有效的 SQL。根据 MSDN 文档:
如果有两个 WHEN MATCHED 子句,则一个必须指定 UPDATE 操作,一个必须指定 DELETE 操作。 …
我在 SQL 中创建了一个表类型:
CREATE TYPE [dbo].[MyObject_TableType] AS TABLE
(
[Name] VARCHAR(MAX) DEFAULT '',
[Index] VARCHAR(MAX) DEFAULT ''
)
Run Code Online (Sandbox Code Playgroud)
我构建了一个DataTable
并用一个填充它DataRow
。我将该表作为参数提供给存储过程:
// Set up connection and command variables (code omitted)
// ...
// Make the data table
var table = new DataTable();
table.Columns.Add("Name");
table.Columns.Add("Index");
// Add one row that is missing an Index
var row = table.NewRow();
row["Name"] = "ObjectOne";
table.Rows.Add(row);
// Make a parameter for the table
var tableParameter = new SqlParameter("MyObjects", SqlDbType.Structured)
{
TypeName = "MyObject_TableType", …
Run Code Online (Sandbox Code Playgroud) sql-server default-value c# user-defined-table-type table-valued-parameters
我有一个网页,用户可以在其中配置 SQL Server 登录名和密码。我正在尝试对此页面实施验证。
我查找了 SQL Server 登录的要求,并找到了这篇 Microsoft 文章。根据那篇文章,SQL Server 登录名不能是保留的登录名。“sa”和“public”作为示例提供。未提供保留登录名的完整列表,我无法通过搜索找到一个。
是否有保留的 SQL Server 登录名列表?如果是这样,我在哪里可以找到它?
是否有基于主键合并行的简写?例如:
MERGE INTO [MyDatabase].[MySchema].[MyTable] AS target
USING [MyLinkedServer].[MyDatabase].[MySchema].[MyTable] AS source
-- The following line is pseudocode illustrating what we want to accomplish
ON (target primary key equals source primary key)
WHEN MATCHED THEN
UPDATE SET target.MyColumn = source.MyColumn
WHEN NOT MATCHED BY TARGET THEN
INSERT (MyCol1, MyCol2, MyCol3)
VALUES (source.MyCol1, source.MyCol2, source.MyCol3);
Run Code Online (Sandbox Code Playgroud)
如果主键包含大量列,则写出条件会很乏味。此外,如果主键发生变化,许多连接和合并可能会突然中断。
您可能会问,“为什么主键会改变?” 真实场景:我们被告知一个对象由其专有名称唯一标识。后来,我们发现如果对象移动到另一个子网,专有名称可能会改变。新要求的推出改变了我们唯一标识对象的方式。这在很多地方破坏了产品。如果我们在主键而不是特定列上进行合并,则可以避免一些混乱。