标签: sql-server-2016

聚集列存储上的非聚集索引存储

在 SQL Server 中,行存储表上的非唯一非聚集索引在非聚集索引结构的所有级别合并了基础对象的书签(RID 或聚集键)。书签作为非聚集索引键的一部分存储在所有索引级别。

另一方面,如果非聚集索引是unique,则书签仅存在于索引的级别 - 不作为键的一部分(实际上,书签作为一个或多个包含的列存在)。

在 SQL Server 2016 中,可以在面向列的表(具有聚集列存储索引的表)上构建非聚集 b 树索引。

  1. 用于聚集列存储表上的非聚集 b 树索引的“书签”是什么?
  2. 上面描述的唯一和非唯一非聚集索引之间的差异是否仍然适用?

sql-server database-internals columnstore sql-server-2016

19
推荐指数
1
解决办法
1266
查看次数

SQL Server - 当性能至关重要时从每个组中选择最近的记录

我运行了一个 SQL Server 2016 数据库,其中有一个包含 100 多万行的下表:

StationId | ParameterId |       DateTime       | Value
    1     |      2      | 2020-02-04 15:00:000 |  5.20
    1     |      2      | 2020-02-04 14:00:000 |  5.20
    1     |      2      | 2020-02-04 13:00:000 |  5.20
    1     |      3      | 2020-02-04 15:00:000 |  2.81
    1     |      3      | 2020-02-04 14:00:000 |  2.81
    1     |      4      | 2020-02-04 15:00:000 |  5.23
    2     |      2      | 2020-02-04 15:00:000 |  3.70
    2     |      4      | 2020-02-04 15:00:000 |  12.20
    3     | …
Run Code Online (Sandbox Code Playgroud)

index sql-server optimization greatest-n-per-group sql-server-2016

19
推荐指数
1
解决办法
3万
查看次数

为什么 AT TIME ZONE 是不确定的?

SQL Server 2016AT TIME ZONE似乎是不确定的。但是,我一直无法找到正式说明这一点或对其背后的推理给出理由的文档。

为什么是AT TIME ZONE不确定的?

显示非确定性的示例

执行:

CREATE TABLE Test (
    LegacyTimestamp DATETIME,
    Timestamp AS LegacyTimestamp AT TIME ZONE 'Eastern Standard Time' PERSISTED
); 
Run Code Online (Sandbox Code Playgroud)

返回以下错误:

Msg 4936, Level 16, State 1, Line 1
Computed column 'Timestamp' in table 'Test' cannot be persisted because the column is non-deterministic.
Run Code Online (Sandbox Code Playgroud)

sql-server timezone sql-server-2016

18
推荐指数
1
解决办法
1428
查看次数

SQL Server--如果存储过程和计划缓存中的逻辑

SQL Server 2012 和 2016 标准:

如果我将if-else逻辑放在存储过程中以执行代码的两个分支之一,取决于参数的值,引擎是否缓存最新版本?

如果在接下来的执行中,参数的值发生了变化,它是否会重新编译并重新缓存存储过程,因为必须执行代码的不同分支?(此查询的编译成本非常高。)

performance sql-server sql-server-2016 query-performance

18
推荐指数
1
解决办法
4572
查看次数

插入时磁盘空间已满,会发生什么?

今天我发现存储我的数据库的硬盘已满。这种情况以前发生过,通常原因很明显。通常有一个错误的查询,这会导致对 tempdb 的大量溢出,它会一直增长到磁盘已满。这次发生的事情不太明显,因为 tempdb 不是驱动器满的原因,而是数据库本身。

事实:

  • 通常的数据库大小约为 55 GB,它增长到 605 GB。
  • 日志文件大小正常,数据文件很大。
  • 数据文件有 85% 的可用空间(我将其解释为“空气”:已使用但已释放的空间。一旦分配,SQL Server 将保留所有空间)。
  • Tempdb 大小正常。

我找到了可能的原因;有一个查询选择了太多的行(错误连接会导致选择 110 亿行,而预计会有几十万行)。这是一个SELECT INTO查询,这让我怀疑是否可能发生以下情况:

  • SELECT INTO 被执行
  • 目标表已创建
  • 数据在选择时插入
  • 磁盘已满,导致插入失败
  • SELECT INTO 被中止并回滚
  • 回滚释放空间(删除已插入的数据),但 SQL Server 不会释放释放的空间。

但是,在这种情况下,我不希望 由 创建的表SELECT INTO仍然存在,它应该被回滚删除。我测试了这个:

BEGIN TRANSACTION 
SELECT  T.x
INTO    TMP.test
FROM    (VALUES(1))T(x)

ROLLBACK

SELECT  * 
FROM    TMP.test
Run Code Online (Sandbox Code Playgroud)

这导致:

(1 row affected)
Msg 208, Level 16, State 1, Line 8
Invalid object name 'TMP.test'.
Run Code Online (Sandbox Code Playgroud)

然而目标表确实存在。不过,实际查询并未在显式事务中执行,这能解释目标表的存在吗?

我在这里勾画的假设是否正确?这是可能发生的情况吗?

sql-server insert rollback sql-server-2016 select-into

18
推荐指数
2
解决办法
2732
查看次数

为什么这个派生表可以提高性能?

我有一个以 json 字符串作为参数的查询。json 是一个纬度、经度对数组。示例输入可能如下所示。

declare @json nvarchar(max)= N'[[40.7592024,-73.9771259],[40.7126492,-74.0120867]
,[41.8662374,-87.6908788],[37.784873,-122.4056546]]';
Run Code Online (Sandbox Code Playgroud)

它调用 TVF 来计算地理点周围 1、3、5、10 英里距离处的 POI 数量。

create or alter function [dbo].[fn_poi_in_dist](@geo geography)
returns table
with schemabinding as
return 
select count_1  = sum(iif(LatLong.STDistance(@geo) <= 1609.344e * 1,1,0e))
      ,count_3  = sum(iif(LatLong.STDistance(@geo) <= 1609.344e * 3,1,0e))
      ,count_5  = sum(iif(LatLong.STDistance(@geo) <= 1609.344e * 5,1,0e))
      ,count_10 = count(*)
from dbo.point_of_interest
where LatLong.STDistance(@geo) <= 1609.344e * 10
Run Code Online (Sandbox Code Playgroud)

json 查询的目的是批量调用此函数。如果我这样称呼它,则性能非常差,仅用了近 10 秒就获得了 4 分:

select row=[key]
      ,count_1
      ,count_3
      ,count_5
      ,count_10
from openjson(@json)
cross apply dbo.fn_poi_in_dist(
            geography::Point(
                convert(float,json_value(value,'$[0]')) …
Run Code Online (Sandbox Code Playgroud)

sql-server sql-server-2016

18
推荐指数
1
解决办法
1825
查看次数

使用 SQL Server 2016 system-versioned temporal table for Slowly-Changed Dimensions 的查询策略

当使用系统版本控制的时态表(SQL Server 2016 中的新功能)时,当使用此功能处理大型关系数据仓库中的缓慢变化维度时,查询创作和性能影响是什么?

例如,假设我有一个Customer带有Postal Code列的 100,000 行维度和一个Sales带有CustomerID外键列的数十亿行事实表。并假设我想查询“按客户邮政编码划分的 2014 年总销售额”。简化的 DDL 是这样的(为了清楚起见省略了很多列):

CREATE TABLE Customer
(
    CustomerID int identity (1,1) NOT NULL PRIMARY KEY CLUSTERED, 
    PostalCode varchar(50) NOT NULL,
    SysStartTime datetime2 GENERATED ALWAYS AS ROW START NOT NULL, 
    SysEndTime datetime2 GENERATED ALWAYS AS ROW END NOT NULL,   
    PERIOD FOR SYSTEM_TIME (SysStartTime, SysEndTime) 
)
WITH (SYSTEM_VERSIONING = ON);

CREATE TABLE Sale
(
    SaleId int identity(1,1) NOT NULL PRIMARY KEY CLUSTERED,
    SaleDateTime …
Run Code Online (Sandbox Code Playgroud)

data-warehouse sql-server slowly-changing-dimension temporal-tables sql-server-2016

17
推荐指数
1
解决办法
1214
查看次数

SQL Server 2016 DB 邮件未发送

我在 SQL Server 2016 上玩得很开心……我的数据库邮件没有发送,而且我已经没有地方可以查看了。我仔细检查了 DBmail 可执行文件的 SQL 帐户权限 - 它已读取并执行。我输入了防火墙出站端口 587 的规则。我尝试了另一个邮件帐户和配置文件,但遇到了相同的未发送问题。日志(db 邮件日志)中唯一的条目是服务的开始和结束。我能找到的任何地方都没有错误。电子邮件似乎只是进入发送队列,永远不会离开它。这些帐户可以自己发送和接收电子邮件,也可以从另一台计算机上的 SQL Server 2014 实例发送和接收电子邮件。

我有一个发送状态为“未发送”的项目队列,除了一长串未发送的邮件外,我还检查了所有正常位置和预期结果:

SELECT * FROM msdb..sysmail_event_log order by log_id DESC

SELECT * FROM dbo.sysmail_mailitems

SELECT * FROM dbo.sysmail_sentitems

USE msdb
SELECT sent_status, *
FROM sysmail_allitems

 SELECT is_broker_enabled FROM sys.databases WHERE name = 'msdb';

 EXECUTE msdb.dbo.sysmail_help_status_sp
Run Code Online (Sandbox Code Playgroud)

我曾尝试将其关闭并再次打开......所以我是否错过了可以阐明这种情况的 DMV 等?这是我搜索中没有的 SQL Server 2016 的已知问题吗?发送此邮件的任何其他可能步骤?

sql-server database-mail sql-server-2016

17
推荐指数
2
解决办法
6万
查看次数

datetime2(0) 与 datetime2(2)

根据文档datetime2 (Transact-SQL)

存储大小
小于 3 的精度为 6 个
字节。精度 3 和 4 为 7 个
字节。所有其他精度需要 8 个字节。

datetime2(0)datetime2(1)、的大小datetime2(2)使用相同的存储量(6 字节)。

我是否正确地说,我可能会datetime2(2)在没有任何额外尺寸成本的情况下使用并获得精度的好处?

请注意:

  • 该列用PK进行索引,形成复合聚集索引(用于表分区)
  • 我不在乎毫秒

datetime2(0)在 where 子句中使用或通过索引查找时,cpu 效率会更高吗?

这是一个庞大的表,因此最小的优化将产生很大的不同。

sql-server datetime2 sql-server-2016

17
推荐指数
1
解决办法
1万
查看次数

SQL Server 2016 Bad Query Plan 每周锁定一次数据库

每周一次,在过去 5 周内,大约在一天中的同一时间(清晨,可能基于人们开始使用它时的用户活动),SQL Server 2016(AWS RDS,镜像)开始超时很多查询。

所有表上的 UPDATE STATISTICS 总是立即修复它。

在第一次之后,我让它每晚(而不是每周)更新所有表上的所有统计信息,但它仍然发生了,(更新统计信息运行后大约 8 小时,但不是每天运行)。

这最后一次,我启用了查询存储,看看我是否能找到它是哪个特定的查询/查询计划。我想我可以将其缩小为一个:

错误的查询计划

找到该查询后,我添加了一个推荐索引,该索引在这个不常用的查询中缺失(但它确实触及了很多常用表)。

错误的查询计划正在执行索引扫描(在只有 10k 行的表上)。其他以毫秒为单位返回的查询计划,虽然用于执行相同的扫描。最新的查询计划,在创建新索引后只查找。但即使没有该索引,99% 的情况下,它也会在几毫秒内返回,但是,每周需要超过 40 秒。

这是从 2012 年迁移到 SQL Server 2016 后开始发生的。

DBCC CHECKDB 没有返回错误。

  1. 新索引是否会解决问题,使其不再选择糟糕的计划?
  2. 我应该“强制”现在运行良好的计划吗?
  3. 我如何确保这不会发生在另一个查询/计划中?
  4. 这是更大问题的征兆吗?

我刚刚添加的索引:

CREATE NONCLUSTERED INDEX idx_AppointmetnAttendee_AttendeeType
ON [dbo].[AppointmentAttendee] ([UserID],[AttendeeType])

CREATE NONCLUSTERED INDEX [idx_appointment_start] ON [dbo].[Appointment]
(
    [ProjectID] ASC,
    [Start] ASC
)
INCLUDE (   [ID],
    [AllDay],
    [End],
    [Location],
    [Notes],
    [Title],
    [CreatedByID]) WITH (PAD_INDEX = OFF, …
Run Code Online (Sandbox Code Playgroud)

sql-server statistics execution-plan sql-server-2016 query-store

17
推荐指数
1
解决办法
8672
查看次数