标签: sql-server-2016

varbinary 的索引维护

我们有一个 SQL 2016 数据库,其中有一个 19 亿行的表,其中有一个 varbinary(255) 列,我们用它来存储同一个表中 nvarchar(2000) 字段的 HashBytes。

我们在 varbinary 字段上有一个非聚集索引,并且我们的索引维护脚本每 2-3 天对此执行一次 REORGANIZE。但这需要10多个小时才能完成。

有什么办法可以提高varbinary字段索引维护的速度吗?

index sql-server varbinary sql-server-2016 index-maintenance

2
推荐指数
1
解决办法
3132
查看次数

带有历史表的 SQL Server 复制

是否可以复制 SQL Server 数据库并让副本拥有临时/历史表?

详细信息:
我有一个生产系统,运行 SQL Server 2014。我想要一个副本数据库,并且我还想跟踪历史更改。

将生产数据库复制到 SQL Server 2016 实例并跟踪时态/历史表的更改将是理想的选择。

这可能吗?
这在 Azure 上可能吗?

编辑:第 2 部分

在大卫·布朗的出色回答和进一步阅读之后,我有了更多的方向和更多的问题。我将使用 Azure SQL 数据库/逻辑服务器。我将使用事务复制,因为 1. Azure SQL 数据库支持它,2. 我们可以在发布者 (Sql Server 2014) 上禁用时态表,并在订阅者 (Azure SQL 数据库/逻辑服务器) 上启用时态表。大卫·布朗的出色回答。

第 2 部分问题:当“发布者”数据库成为发布者时,它会承受多少额外负载?

设置此功能时如何避免停机和锁定发布者?

我有多个“发布者”数据库。我可以在一个 Azure SQL 数据库/逻辑服务器实例上拥有多个订阅者数据库吗?

replication sql-server sql-server-2014 temporal-tables sql-server-2016

2
推荐指数
1
解决办法
963
查看次数

阻止对主 AG 副本进行读取访问,但允许在可读辅助副本上进行读取访问

我们有一个独特的情况,我们希望允许用户使用 SSMS 查询数据库的可读辅助副本以进行临时报告,但不允许他们从主副本中读取数据。我们设置了只读路由来完成此任务。这也是 SQL 2016 上的全部。

我最初的想法是在主副本和辅助副本上创建登录名,并授予对相关数据库的读取访问权限。然后我们将拒绝连接或禁用当前主副本上的登录。在 SSMS 中,用户可以使用 ApplicationIntent=ReadOnly 连接到侦听器,并路由到辅助副本,而无需接触主副本。

我们将使用基本逻辑在主副本服务器和辅助副本服务器上设置一个简单的作业:如果当前服务器=主服务器,则禁用登录;如果当前服务器 = 辅助服务器,则启用登录。

问题是,当在主服务器上禁用登录时,以只读意图连接到侦听器时,我会遇到登录失败。当我在主副本上重新启用登录时,它工作得很好,并且连接已正确路由到可读的辅助副本。

我在主服务器上设置了跟踪,果然,我可以看到登录连接并在主副本上的 master 和 msdb 中运行一些系统类型查询 - 即使我在 SSMS 中使用 ApplicationIntent=ReadOnly 进行连接。我不确定这是否是 SSMS 在幕后执行的操作,或者是否是登录通过只读路由过程的默认行为。

以下是我在主数据库上使用快速分析器跟踪捕获的查询:

--msdb query

    select 
        case 
            when object_id('dbo.sysdac_instances') is not null then 1             
        else
            0 
        end

--master query

SELECT
dtb.name AS [Name],
dtb.database_id AS [ID],
CAST(has_dbaccess(dtb.name) AS bit) AS [IsAccessible]
FROM
master.sys.databases AS dtb
ORDER BY
[Name] ASC
Run Code Online (Sandbox Code Playgroud)

以前有人处理过这种情况吗?看来我们基本上需要允许主副本上的登录连接权限,同时拒绝其对主副本上 AG 中的数据库的读取访问权限,但授予该登录权限以读取可读辅助副本上的数据库。

另一种选择是创建一个直接指向辅助副本的 DNS 条目,但我们不能保证该副本始终是辅助副本,因为可能会发生故障转移。

sql-server availability-groups read-only-database sql-server-2016

2
推荐指数
1
解决办法
3133
查看次数

BST/GMT 转换为 UTC 时间

无论如何,将存储在 DB 中的 BST 日期时间转换为 UTC

查看了“时区”,但似乎是从 UTC 到其他时间。

数据库将日期时间存储为 BST/GMT 历史上需要将这些日期时间返回为 UTC

SELECT CONVERT(datetime,GETDATE()) AT TIME ZONE 'UTC' 
Run Code Online (Sandbox Code Playgroud)

例如

2019-07-08 12:01:55.060 ->  2019-07-08 11:01:550
Run Code Online (Sandbox Code Playgroud)

需要回溯大量历史日期数据,因此可能是 GMT 或 BST,具体取决于一年中的时间以及哪一年将确定回溯的切换日期

下面的示例,我存储了 GMT/BST 时区时间,需要使用 UTC 格式

DECLARE @dayLight TABLE(season VARCHAR(50), [gmt/bst] datetime, uct Datetime) 
INSERT INTO  @dayLight
VALUES('winter','2019-02-10 15:00:00','2019-02-10 15:00:00')
       ,('winter','2019-03-30 15:00:00','2019-03-30 15:00:00')
       ,('summer','2019-03-31 02:00:00','2019-03-31 01:00:00') --cut over
       ,('summer','2019-04-15 15:00:00','2019-03-30 14:00:00')
       ,('summer','2019-10-27 02:00:00','2019-10-27 01:00:00') --cut over
       ,('winter','2019-10-27 03:00:00','2019-10-27 03:00:00')

SELECT season,uct,[gmt/bst] FROM @dayLight     
Run Code Online (Sandbox Code Playgroud)

sql-server sql-server-2016

2
推荐指数
1
解决办法
3350
查看次数

如何在不影响文本格式的情况下一次将 8,000 多个字符打印到 SSMS 消息窗口?

每当我编写动态 SQL 时,我通常会PRINT @DynamicSQL在该语句正上方的注释中包含一条语句EXEC sp_ExecuteSQL @DynamicSQL,以便在需要时可以轻松读取和调试动态 SQL。

我意识到 PRINT 语句在截断字符串之前有 8,000 个字符的限制。我知道我可以循环遍历我的 @DynamicSQL 变量,将 8,000 划分为它的长度,并每次迭代打印每个 8,000 块,但是随后您会丢失 @DynamicSQL 中的语句跨两个块的格式,这违背了我的目的。

有没有人找到更好的方法来在打印超过 8,000 个字符的字符串时保留格式?...也许通过自定义函数或过程?

sql-server ssms sql-server-2016

2
推荐指数
1
解决办法
3129
查看次数

我可以在 DELETE 时避免 TABLOCKX 吗?

目标

删除三个表中数十亿条旧记录(大约 600GB),停机时间为零。

方法论和背景

我计划一次删除与 100 万个 MyID 关联的批量记录(即 MyID 介于 1 和 1000000 之间)。当删除运行时,其中两个表将非常热,但第三个表上的活动可以安全地暂停。在两个热表中,MyID是聚簇键。在第三个冷表中,我在 MyID 上有一个非聚集索引。

除了 DELETE 操作之外,热表中的其他活动将包括 INSERT,可能每秒几次。MyID 是一个 IDENTITY,新插入的记录不会在任何 DELETE 批次的范围内。

如果有助于了解潜在性能,则在由 MyID 聚集的表上对这些行的样本批次进行聚合的 SELECT 花费的时间不到 1 秒,而在非聚集的表上则花费大约 2 秒。我没有这个特定数据库的产品副本可供使用,所以我不能说删除需要多长时间,但是一旦我将其部署到 DEV,我就会有一个更好的想法。

旁注:为了解决日志大小问题,我将这些批次包装在事务中,并将 TLog 备份频率从 15 分钟提高到 5 分钟。我有 150GB 的可用日志空间。

问题

我在 MS 文档中读到:

默认情况下,DELETE 语句始终在其修改的表上获取排它 (X) 锁,并保持该锁直到事务完成。

我对使用锁定提示非常谨慎,但在这种情况下我可以安全地使用锁定提示来避免 TABLOCKX 吗?除了锁定提示之外还有其他方法可以避免 TABLOCKX 吗?

sql-server delete locking sql-server-2016

2
推荐指数
1
解决办法
5678
查看次数

无法从 .BAK 文件恢复数据库

我正在尝试恢复我的 .bak 文件,但我不断收到错误消息

数据库“DataWarehouse”恢复失败。(Microsoft.SqlServer.Management.RelationalEngineTasks)
System.Data.SqlClient.SqlError:还原数据库异常终止(Microsoft.SqlServer.SmoExtended)

我尝试恢复的 .bak 文件是否已损坏?

我采取的步骤是

1) 右键单击​​服务器名称并选择恢复
2) 导航到 .bak 文件的位置
3) 单击“确定”

sql-server sql-server-2016

2
推荐指数
1
解决办法
8987
查看次数

使用服务器角色向所有数据库授予权限

我知道这个问题已经被问过很多次了,但他们都 3 岁以上了,所以我想再问一次,碰碰运气。

我需要向 MSSQL 服务器上的所有数据库授予读取权限。我想使用服务器角色来实现这一点。

我已经创建了具有以下权限的服务器角色

CREATE SERVER ROLE ReadOnlyAccess 
GO
GRANT VIEW ANY DEFINITION TO ReadOnlyAccess
Go
GRANT VIEW ANY DATABASE TO ReadOnlyAccess
GO
GRANT VIEW SERVER STATE TO ReadOnlyAccess
GO
GRANT CONNECT SQL TO ReadOnlyAccess;
GO
Run Code Online (Sandbox Code Playgroud)

将用户分配给此角色允许我连接到服务器但不扩展任何数据库。我认为“授予查看任何数据库”将是赋予这些权利的权利,但我错了......

有没有一种方法可以实现此目的,而无需在每个数据库上为用户授予 db_datareader 数据库角色?新的数据库不断被创建,因此手动执行此操作将是一场噩梦。我猜想创建一个每隔几个小时运行一次的作业就可以解决问题,但我仍然宁愿通过服务器角色来完成它。

有任何想法吗?我使用的是 SQL 2016 及更高版本。

sql-server permissions sql-server-2016

2
推荐指数
1
解决办法
5797
查看次数

是否可以更改驱动器名称/标签(不是驱动器号!)

我意识到这可能是一个简单的问题,但如果我包含 SQL Server,我的搜索只会返回驱动器号或数据库名称的结果。请随时向我指出现有的文章或答案,并提前道歉:)

我继承了一个环境,其中包含多个支持多个 SharePoint 2013 和 2016 场的 SQL Server 2014 和 2016 服务器(也有一些是集群服务器)。以前的 SA 为驱动器命名/标记了一些相当模糊的名称,我想通过重命名驱动器来避免自己继续混淆每个包含的内容。这是一个坏主意吗?我似乎无法在我的环境中找到任何专门提到驱动器名称的东西,一切似乎都选择了驱动器号,在某些情况下,驱动器名称被呈现为信息。

驱动器名称只是一个描述,实际上并没有将驱动器本身识别为任何系统,我对吗?

sql-server sharepoint sql-server-2014 sql-server-2016

2
推荐指数
1
解决办法
860
查看次数

为什么添加 WHERE 子句会破坏我的工作查询,并出现错误“由于定义的提示,查询处理器无法生成查询计划...”?

我有以下(愚蠢地简化的)查询,它利用两个引用同一个表的 CTE 并将它们相互连接:

WITH CTE1 AS
(
    SELECT dbo.RemoveNonNumericCharacters(PhoneNumber) AS PhoneNumberCleaned
    FROM PhoneNumbersTable
    GROUP BY dbo.RemoveNonNumericCharacters(PhoneNumber)
),
CTE2 AS
(
    SELECT CTE1.PhoneNumberCleaned
    FROM CTE1
    INNER HASH JOIN PhoneNumbersTable
        ON CTE1.PhoneNumbersCleaned = dbo.RemoveNonNumericCharacters(PhoneNumbersTable.PhoneNumber)
    WHERE PhoneNumbersTable.AreaCode IN (718, 212)
)

SELECT PhoneNumberCleaned
FROM CTE2
Run Code Online (Sandbox Code Playgroud)

注意HASH JOIN里面发生的事情CTE2。到目前为止,这一切都运作良好。

如果我将以下WHERE子句添加到最终SELECT查询中,那么我的整个查询现在变为:

WITH CTE1 AS
(
    SELECT dbo.RemoveNonNumericCharacters(PhoneNumber) AS PhoneNumberCleaned
    FROM PhoneNumbersTable
    GROUP BY dbo.RemoveNonNumericCharacters(PhoneNumber)
),
CTE2 AS
(
    SELECT CTE1.PhoneNumberCleaned
    FROM CTE1
    INNER HASH JOIN PhoneNumbersTable
        ON CTE1.PhoneNumbersCleaned …
Run Code Online (Sandbox Code Playgroud)

sql-server hints execution-plan errors sql-server-2016

2
推荐指数
1
解决办法
866
查看次数