很久以前我遇到过这个问题,我找到了一个适合我的解决方法并忘记了它。
但是现在在 SO 上有这个问题,所以我愿意提出这个问题。
有一个视图以非常简单的方式(订单 + 订单行)连接几个表。
在没有where子句的情况下查询时,视图返回几百万行。
然而,从来没有人这样称呼它。通常的查询是
select * from that_nasty_view where order_number = 123456;
Run Code Online (Sandbox Code Playgroud)
这将返回 5m 中的大约 10 条记录。
一件重要的事情:视图包含一个窗口函数,rank(),它由始终查询视图所使用的字段精确分区:
rank() over (partition by order_number order by detail_line_number)
Run Code Online (Sandbox Code Playgroud)
现在,如果使用查询字符串中的文字参数查询此视图,完全如上所示,它会立即返回行。执行计划很好:
order_number(返回 10 行)。然而,当以参数化的方式调用视图时,事情变得很糟糕:
Index scan在所有表上忽略索引。返回 5m 行。partitions 的窗口(大约 500k 个窗口)。Filter 从 5m 中取出 10 行。在涉及参数的所有情况下都会发生这种情况。它可以是 SSMS:
declare @order_number int = 123456;
select * from that_nasty_view where order_number = @order_number; …Run Code Online (Sandbox Code Playgroud) 我有一个通用日志表,大约 5m 行。
有一个存储事件类型的“强类型”字段,以及一组包含与事件相关的数据的“弱类型”列。也就是说,那些“松散类型”列的含义取决于事件的类型。
这些列定义为:
USER_CHAR1 nvarchar(150) null,
USER_CHAR2 nvarchar(150) null,
USER_CHAR3 nvarchar(150) null,
USER_CHAR4 nvarchar(150) null,
USER_CHAR5 nvarchar(150) null,
USER_INTEGER1 int null,
USER_INTEGER2 int null,
USER_INTEGER3 int null,
USER_INTEGER4 int null,
USER_INTEGER5 int null,
USER_FLAG1 bit null,
USER_FLAG2 bit null,
USER_FLAG3 bit null,
USER_FLAG4 bit null,
USER_FLAG5 bit null,
USER_FLOAT1 float null,
USER_FLOAT2 float null,
USER_FLOAT3 float null,
USER_FLOAT4 float null,
USER_FLOAT5 float null
Run Code Online (Sandbox Code Playgroud)
每种类型中的第 1 列和第 2 列都被大量使用,但从第 3 列开始,很少有事件类型会提供如此多的信息。因此,我决定将每种类型的第 3-5 列标记为SPARSE.
我首先进行了一些分析,发现实际上,每一列中至少 80% 的数据是null …
在我永无止境地寻求通过保存交易射击自己的过程中,我似乎找到了更多实现任务目的的方法。这次的save transaction子句本身是没问题的,不过正因为如此,我才写了下面的代码。
考虑以下带有嵌套错误处理程序的完整示例:
begin try
begin try
select 'Step 1';
end try
begin catch
select 'Step 1 handler - handling ''' + error_message() + '''';
goto commit_and_exit;
end catch;
begin try
select 'Step 2';
raiserror('Step 2 error', 16, 1);
end try
begin catch
select 'Step 2 handler - handling ''' + error_message() + '''';
goto commit_and_exit;
end catch;
end try
begin catch
select 'Outer handler - handling ''' + error_message() + '''';
goto commit_and_exit;
end catch
commit_and_exit:
raiserror('Error raised for …Run Code Online (Sandbox Code Playgroud)
这现已发布到 Connect:SQL Server 2012 中的 FORMAT() 函数拒绝了不变区域性标识符。(Connect 已停用。)
现已发布到feedback.azure.com。
我正在尝试让format()SQL Server 2012 中的内置函数使用不变区域性。
文档中说该函数接受 .NET 区域性标识符作为第三个参数。不变区域性的标识符是一个空字符串:
您可以通过
""在调用CultureInfo实例化方法时使用空字符串 ( )按名称指定不变区域性。
但是,这不适用于 SQL Server:
Run Code Online (Sandbox Code Playgroud)select format(getdate(), N'g', '');
消息 9818,级别 16,状态 1,第 1 行
函数调用中提供的区域性参数 '' 不受支持。
还记录了不变文化与英语相关联,但与任何国家/地区无关。有人会认为这允许'en'作为标识符传递,但是,在 .NET 中,CultureInfo.InvariantCulture.Equals(CultureInfo.GetCultureInfo(""))yields true,但CultureInfo.InvariantCulture.Equals(CultureInfo.GetCultureInfo("en"))Gives false,所以它们实际上并不相同。
那么如何让 SQL Server 使用不变文化呢?
(注意:我有兴趣使内置的东西工作。我已经有了自己的 CLR 函数来做到这一点,我打算删除它们以支持现在的内置功能)。
Microsoft SQL Server 2012 (SP1) - 11.0.3128.0 (X64)
2012 年 …
将我们的数据库从 SQL Server 2012 迁移到 2016,我们无法重新创建涉及用 VBScript 编写的 ActiveX 脚本步骤的 SQL 代理作业。
错误消息表明这'ACTIVESCRIPTING'不是 的@subsystem参数的允许值sp_add_jobstep。
我知道 ActiveX 脚本被标记为“将在SQL Server的未来版本中删除”。但是,我看不到在此版本的 SQL Server 中实际删除了有关它的任何内容。
SQL Server 文档似乎表明它在 SQL Server 2016 中仍然可用:
sp_add_jobstep2017 年 3 月更新的文档仍@subsystem ='ACTIVESCRIPTING'列为可用。在@subsystem ='ACTIVESCRIPTING'事实上,在一个未公开的方式偷偷取走,还是我们错过了一个可安装组件,支持呢?
我有一个标量函数,它返回一个大的 XML,它是通过一堆发票创建的。
可以使用几种不同的方法计算要提供给函数的确切发票列表,但函数每次都是相同的。出于这个原因,我声明了一个用户定义的表类型来包含表中的主键eInvoice.Header并将其传递给函数。这样我就可以有几个不同的函数来决定要处理哪些发票,并且只有一个函数可以实际生成 XML:
create function eInvoice.GetRelevantLinesInOneWay()
returns table ...
create function eInvoice.GetRelevantLinesInAnotherWay()
returns table ...
create function eInvoice.GetXML(@lines eInvoice.InvoicePrimaryKeys readonly)
returns xml
as
begin
declare @x xml;
with xmlnamespaces(N'important namespace' as pro)
select @x = (
select
...
from
eInvoice.Header h
inner join @lines l on h.ST_PRIMARY = l.invoice_row_id
for xml path(N'pro:Import'), type
);
return @x;
end;
Run Code Online (Sandbox Code Playgroud)
不幸的是,这种设置已被证明是非常脆弱的。
通常@lines包含大约 150 行(大约1min eInvoce.Header)。正确的执行计划是在 上使用索引查找ST_PRIMARY,当我将 的主体eInvoice.GetXML作为临时查询执行时,总是会发生这种情况。
然而,当我将它存储为一个函数时,它会按预期工作一段时间,然后发生了一些事情(太多行@lines,比如大约300 …
performance sql-server execution-plan sql-server-2012 table-valued-parameters query-performance
sql-server ×2
format ×1
jobs ×1
null ×1
performance ×1
scripting ×1
storage ×1
t-sql ×1
view ×1