AskOverflow.Dev

AskOverflow.Dev Logo AskOverflow.Dev Logo

AskOverflow.Dev Navigation

  • 主页
  • 系统&网络
  • Ubuntu
  • Unix
  • DBA
  • Computer
  • Coding
  • LangChain

Mobile menu

Close
  • 主页
  • 系统&网络
    • 最新
    • 热门
    • 标签
  • Ubuntu
    • 最新
    • 热门
    • 标签
  • Unix
    • 最新
    • 标签
  • DBA
    • 最新
    • 标签
  • Computer
    • 最新
    • 标签
  • Coding
    • 最新
    • 标签
主页 / user-150011

J.D.'s questions

Martin Hope
J.D.
Asked: 2024-10-12 01:46:33 +0800 CST

如何正确创建空间索引并编写利用该空间索引的 SARGable 查询?

  • 7

我似乎无法让 SQL Server 利用对象上的基本空间索引GEOGRAPHY来执行最简单的查询。

这里是dbfiddle.uk 复制版GEOGRAPHY,演示了如何创建一个带有名为 的列的简单表Coordinates,向该表添加 1 个带有多边形的行,然后在该Coordinates列上创建空间索引。

该查询看起来应该是 SARGable,但我仍然得到聚集索引扫描,而不是在空间索引上进行非聚集索引查找:

聚集索引扫描

如果我尝试强制索引提示,我会收到经典错误:

消息 8635,级别 16,状态 4,第 15 行

查询处理器无法为带有空间索引提示的查询生成查询计划。原因:空间索引不支持谓词中提供的比较器。尝试删除索引提示或删除 SET FORCEPLAN。

因此,并不是 SQL Server 认为聚集索引扫描性能更高,而是它甚至无法为空间索引提出查询计划。

根据微软关于空间索引的文档,该STDistance()函数应该适用于空间索引可优化的谓词:

空间索引支持以下谓词形式:

  • 地理1.STDistance(地理2) <= 数字

我是不是太笨了?

sql-server
  • 1 个回答
  • 97 Views
Martin Hope
J.D.
Asked: 2024-03-14 05:46:16 +0800 CST

我的队列表实现竞争条件安全吗?

  • 11

大家好,比我聪明的人!我创建了一个队列表系统,但它似乎太简单,无法避免竞争条件。我是否遗漏了什么或者以下竞争条件安全吗?

模式

我有一张桌子,我们称之为ProductQueue:

CREATE TABLE dbo.ProductQueue
(
    SerialId BIGINT PRIMARY KEY,
    QueuedDateTime DATETIME NOT NULL -- Only using this for reference, no functionality is tied to it
);

我有添加到队列的过程,称为AddToProductQueue:

CREATE PROCEDURE dbo.AddToProductQueue (@SerialId BIGINT)
AS
BEGIN
    INSERT INTO dbo.ProductQueue (SerialId, QueuedDateTime)
    OUTPUT Inserted.SerialId
    SELECT @SerialId, GETDATE();
END

我还有一个从队列中删除的过程,称为RemoveFromProductQueue:

CREATE PROCEDURE dbo.RemoveFromProductQueue (@SerialId BIGINT)
AS
BEGIN
    DELETE FROM dbo.ProductQueue
    OUTPUT Deleted.SerialId
    WHERE SerialId = @SerialId;
END

注意,对于源数据库/系统中的SerialIda 来说是全局唯一的。Product即,a 的两个实例Product不可能具有相同的SerialId。这就是数据库方面的范围。

工作流程

  • 我有一个每小时运行的申请流程。
  • SerialIds该进程从源系统获取变量列表。
  • 它迭代地调用其列表中AddToProductQueue每个的过程SerialId。
  • 如果该过程尝试插入表SerialId中ProductQueue已存在的 ,则会引发主键冲突错误,并且应用程序进程会捕获该错误并跳过该错误SerialId。
  • 否则,该过程会成功地将其添加SerialId到ProductQueue表中并将其返回给应用程序进程。
  • 然后,应用程序进程将成功排队的添加SerialId到单独的列表中。
  • 应用程序进程完成迭代所有要SerialIds入队的候选者列表后,它会迭代其成功排队的新列表,并在每个的单独线程SerialIds中对它们进行外部工作。(这项工作与数据库无关。)SerialId
  • 最后,当每个线程完成其外部工作时,该异步线程中的最后一步是通过调用该过程将其SerialId从表中删除。(请注意,会实例化一个新的数据库上下文对象,并为每个异步调用此过程创建一个新连接,因此它在应用程序端是线程安全的。)ProductQueueRemoveFromProductQueue

附加信息

  • 表上没有任何索引ProductQueue,并且表中的行数永远不会超过 1,000 行。(实际上,大多数时候它实际上只有几行。)
  • 相同的SerialId可以再次成为在应用程序进程的未来执行时被重新添加到队列表中的候选者。
  • 没有安全措施可以阻止应用程序进程的第二个实例同时运行,无论是意外还是第一个实例运行时间超过 1 小时等。(这是我最关心的并发部分。)
  • 队列表和过程所在的数据库(以及正在建立的连接)的事务隔离级别是默认隔离级别Read Committed。

潜在问题

  • 应用程序进程的运行实例以未处理的方式崩溃,卡SerialIds在队列表中。这对于业务需求来说是可以接受的,我们计划提供异常报告来帮助我们手动修复这种情况。
  • 应用程序进程同时执行多次,并SerialIds在其初始源列表中的实例之间获取一些相同的内容。我还无法想到这种情况的任何负面影响,因为排队过程是原子的,并且SerialIds由于该原子排队过程,应用程序进程将处理的实际列表应该是独立的。我们并不关心应用程序进程的哪个实例实际处理每个进程SerialId,只要SerialId两个进程实例不同时处理相同的进程即可。
sql-server
  • 4 个回答
  • 863 Views
Martin Hope
J.D.
Asked: 2023-11-18 01:36:46 +0800 CST

如何总结事件的不同总时间,忽略时间中的重复重叠?

  • 8

我有下EventTimes表:

DROP TABLE IF EXISTS dbo.EventTimes;
CREATE TABLE dbo.EventTimes
(
  EventTimeKeyId INT IDENTITY(1,1) PRIMARY KEY,
  EventId INT NOT NULL,
  StartTime TIME NOT NULL,
  EndTime TIME NOT NULL
);

具有以下数据:

-- Event 1
INSERT INTO dbo.EventTimes (EventId, StartTime, EndTime)
VALUES 
  (1, '04:00:00', '14:00:00'), 
  (1, '06:00:00', '11:00:00'), 
  (1, '09:00:00', '12:00:00'), 
  (1, '13:00:00', '14:00:00'), -- Gap between this row and the next row
  (1, '02:30:00', '04:00:00'); -- Notice the half-hour on this one

-- Event 2
INSERT INTO dbo.EventTimes (EventId, StartTime, EndTime)
VALUES 
  (2, '00:00:00', '06:00:00'), -- Gap between this row and the next row
  (2, '09:00:00', '13:00:00'), 
  (2, '11:00:00', '15:00:00');

注意:

  • 同一Event时间范围可以有两个相互重叠的时间范围。例如,Event从凌晨 4 点到下午 2 点以及早上 6 点到上午 11 点也是如此。
  • 两个时间范围之间也可能存在间隙。例如Event,下午 1 点至 2 点以及下午 2:30 至 4 点也是如此。

最终目标:

我正在尝试计算给TotalTime定的Event忽略重复的重叠时间。例如,对于上午 9 点到下午 1 点和上午 11 点到下午 3 点的范围集,不同的TotalTime时间应该是 6 小时(上午 9 点到下午 3 点)。相反,我也不想计算两个时间范围之间的间隙时间。因此,对于下午 1 点到 2 点以及下午 2:30 到 4 点的范围集,TotalTime应该是 2.5 小时。(请注意,这些只是上面完整示例的子集,最终结果应该是每个 的所有这些唯一时间的总和Event。)

不应TotalTime超过 24 小时,这些时间都在一天之内(TIME数据类型也是如此)。

上面脚本中提供的示例的预期最终结果:

示例最终结果

dbfiddle.uk 供参考。


其他信息:

  • 如果使用日期时间更容易,请随意将数据类型从 更改TIME为DATETIME。我可以将结果转换回来,没问题。

  • 我相信需要某种递归来解决这个问题。我觉得我已经非常接近解决方案,但还没有完全实现。

在 2:30 - 4:00 和 4:00 - 14:00 等情况下,我预计总时间为 11.5 小时。

sql-server
  • 2 个回答
  • 141 Views
Martin Hope
J.D.
Asked: 2023-06-03 00:32:57 +0800 CST

是否有可靠的方法来检查触发的触发器是否是来自另一个*特定*触发器的 DML 操作的结果?

  • 17

有什么方法可以从触发器内部判断,当它被触发时,它是由于另一个特定触发器中发生的 DML 操作而被触发的?

有没有机会在函数中公开有关调用堆栈的任何信息EVENTDATA()?还是其他功能?我宁愿不必粉碎 XML。?

我的理想目标是从第二个触发器的范围内获取执行导致第二个触发器触发的 DML 的原始触发器的名称。但我也对类似的识别来源的方式持开放态度。

我可以完全控制所讨论的两个触发器的代码。

sql-server
  • 1 个回答
  • 361 Views
Martin Hope
J.D.
Asked: 2022-08-02 08:55:31 +0800 CST

当临时表上发生 DML 和 DDL 更改时,历史表中的相关更改是否也会记录在事务日志中?

  • -1

当对Temporal Table执行 DML 和 DDL 查询时,这些更改会适当地传播到相关的 History 表。例如UPDATE,临时表会导致将新记录INSERT编辑到历史表中以反映该更改。

是INSERT记录在事务日志中的历史表以及其他传播的更改吗?

这是否意味着启用临时表将有效地使通过事务日志的数据量翻倍(至少对于恢复模型设置为完整的数据库)?

sql-server transaction-log
  • 1 个回答
  • 64 Views
Martin Hope
J.D.
Asked: 2022-02-04 11:15:04 +0800 CST

查询存储的总体资源消耗报告是告诉我我的数据库做得很糟糕还是只是数字被破坏了?

  • 7

最近,我们将其中一台生产服务器从 SQL Server 2016 升级到了 SQL Server 2019 (CU 15)。这对我来说是在我们的主应用程序数据库上启用查询存储的绝佳机会。它已经运行了几天,这就是总体资源消耗报告显示的内容:

整体资源消耗报告

在屏幕截图中,我挑选了一些看起来很疯狂的数字(在启用查询存储的第一天)并将它们标准化为更容易讨论的度量单位。一天之内,逻辑读取消耗约 183 TB 的数据,或内存消耗约 5 TB的数据,在此服务器上似乎几乎是不可能的。

这个数据库是数据库中的 John Smith,数据文件只有100 GB ,日志文件只有200 GB。最多可能有 100 个不同的用户全天连接到它,而且一天内不会创建大量交易。服务器本身只为其配置了32 GB的内存。要消耗5 TB的内存,分配的内存需要在一天内被填满150 次以上。

我能想到的唯一其他可能相关的信息是在升级之后,我们立即将此数据库的“兼容性级别”设置为 150(SQL Server 2019)并关闭“旧基数估计”设置。我知道这并不理想,最好在收集基线指标时让尘埃落定,但升级的部分原因是为了解决一些紧急的性能问题,这些设置组合实际上在我们的测试中最有效(而且似乎仍然工作得很好)。

我们之前遇到的一些性能问题是由于疯狂的基数估计,如果查询存储使用估计的数据点,那么我实际上可以看到这个报告的数字是相关的,但我不得不想象报告是使用实际数据点?虽然如果这是另一个迹象表明我的生产服务器/数据库在我持续征服以解决基数估计问题时配置方式存在根本性错误,那将会很有趣。

我读错了这些数字,是查询存储出错了,还是我的服务器吐司?

sql-server performance
  • 2 个回答
  • 348 Views
Martin Hope
J.D.
Asked: 2022-01-16 07:26:54 +0800 CST

门号 1、2 还是 3?...从 SQL Server 2016 到 SQL Server 2019 的就地升级导致安全性更改、错误或升级失败?

  • 5

我做了什么:

ServerA最近,我测试了在运行 SQL Server 2016 (SP 2 CU17) 标准版到 SQL Server 2019 标准版的开发服务器上进行就地升级。(我知道这不是进行升级的首选方式,而只是在开发服务器上进行测试,所以没有伤害没有犯规。)

在安装向导期间,其中一个步骤挂了很长时间,所以我的同事单击下一步按钮跳过该步骤。我不太记得它是哪一步,但我相信它是产品更新或安装设置文件步骤。我记得它接下来说它跳过了几种不同类型的下载。其余的安装顺利,成功完成。

我能够启动实例、登录并访问我们的数据库。然后我将数据库兼容级别提高到 150(SQL Server 2019 的兼容级别)。我运行了一些性能测试查询,然后最终决定打开 Legacy Cardinality Estimator。到目前为止,一切似乎都在工作。

发生的事情是:

然后我注意到了一些有趣的东西ServerB,另一台已经在运行 SQL Server 2019 的开发服务器,并且有一个链接服务器设置指向ServerA. 一切都运行良好ServerB,除了引用链接服务器上的视图的任何查询,该视图在ServerA其中使用了模式绑定标量函数。我收到错误The EXECUTE permission was denied on the object 'MyFunction', database 'Database1OnServerA', schema 'dbo'。如果我返回ServerA并更改WITH SCHEMABINDING注释掉的行的函数,则ServerB能够从再次引用该函数的视图中进行选择。

附加信息:

链接服务器对象中使用的帐户是 SQL Server Login on ServerA,只有db_datareader映射到它Database1的角色(当然ServerA除了Public数据库角色)。它没有设置额外的细化权限,它也只分配了Public服务器角色。

有趣的是,我的问题的另一种解决方案是授予链接服务器帐户的权限EXECUTE或专门授予链接服务器帐户的权限。但是我不必在升级到 SQL Server 2019 之前授予权限,并且我的生产服务器(在此测试升级之前非常类似地镜像我的开发服务器)目前也没有为链接服务器帐户提供权限。Database1ServerAMyFunctionEXECUTEServerAEXECUTE

1、2 或 3 号门:

  1. 从 SQL Server 2016 到 SQL Server 2019 发生了一些我没有意识到的与安全相关的变化,或者......
  2. 这听起来像是我遇到的错误还是...
  3. 你认为我把就地升级搞砸了ServerA吗?

关于为什么在从 SQL Server 2016升级到 SQL Server 2019后,仅通过链接服务器访问的架构绑定函数的权限ServerB上出现权限错误的任何其他想法,简单地说?EXECUTEServerAServerA

sql-server sql-server-2016
  • 1 个回答
  • 196 Views
Martin Hope
J.D.
Asked: 2021-09-25 08:36:54 +0800 CST

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

  • 2

我有以下(愚蠢地简化)查询,它利用两个 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

注意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 = dbo.RemoveNonNumericCharacters(PhoneNumbersTable.PhoneNumber)
    WHERE PhoneNumbersTable.AreaCode IN (718, 212)
)

SELECT PhoneNumberCleaned
FROM CTE2
WHERE PhoneNumberCleaned = 'SomePhoneNumberInTheResultSet' -- E.g. 7183998888

然后我得到经典错误:

消息 8622,级别 16,状态 1,第 50 行 由于此查询中定义的提示,查询处理器无法生成查询计划。在不指定任何提示且不使用 SET FORCEPLAN 的情况下重新提交查询。

仅当我在WHERE子句中使用的值实际存在于结果集中时,才会发生这种情况。如果我选择任何不存在的值,那么我不会收到上述错误。

现在显然我的例子对于正在发生的事情有点愚蠢,我可以用几种不同的方式重写它来修复它,但我更好奇为什么会发生这种情况?如果 SQL Server 引擎能够生成返回所有记录的查询计划,为什么它无法在该查询计划的末尾为我在WHERE子句中过滤的标量值添加额外的过滤运算符?

这是我的函数的黑盒代码dbo.RemoveNonNumericCharacters(注意我没有写这个):

CREATE FUNCTION [dbo].[RemoveNonNumericCharacters] (@strText VARCHAR(1000))
RETURNS VARCHAR(1000)
AS
BEGIN
    WHILE PATINDEX('%[^0-9]%', @strText) > 0
    BEGIN
        SET @strText = STUFF(@strText, PATINDEX('%[^0-9]%', @strText), 1, '')
    END
    RETURN @strText
END

另请注意, 中的列PhoneNumber是PhoneNumbersTable类型VARCHAR(20)。

sql-server sql-server-2016
  • 1 个回答
  • 281 Views
Martin Hope
J.D.
Asked: 2021-09-18 09:43:30 +0800 CST

为什么对我的数据库进行完整备份还原时出现错误“RESTORE 只能在还原完整备份时创建数据库...”?

  • 3

我已经制定了维护计划,每天对服务器上的所有数据库进行完整备份。我还设置了第二个维护计划,每 5 分钟备份一次事务日志。事务日志备份作业在晚上 11 点到凌晨 1 点之间停止并重新启动,以允许进行服务器级备份(在基础架构团队的建议下,可能会重新访问)。我不认为这应该是一个问题,因为我有另一台服务器遵循相同的模式,并且它的备份没有问题。

我正在尝试验证我的备份是否正常工作,但是每当我尝试使用之后的任何事务日志备份来恢复完整备份时,我都会立即收到以下错误:

备份还原错误

我正在尝试将备份还原到单独的服务器(相同的 SQL Server 版本),其主要目的是测试数据库备份的完整性。我正在尝试恢复的数据库当前在该服务器上不存在。

如果它有任何相关性,这些是我正在使用的还原选项:

恢复选项

在Aaron Bertrand 对类似问题的有趣回答之后,我现在正在使用该RESTORE HEADERONLY FROM DISK命令调查一些事情。首先,这些是我的完整备份文件的结果:

完整备份标头

该完整备份中仅存储一个数据库/文件。

此外,如果我RESTORE HEADERONLY FROM DISK在最后一次完整备份之后运行我的第一个事务日志备份文件、完整备份文件本身以及最后一次完整备份之前的最后一个事务日志备份文件,我会注意到以下 LSN:

LSN

我认为DatabaseBackupLSN所有备份的 都应该与FirstLSN这些备份之前的最后一个完整备份相匹配。对我来说奇怪的是,它们似乎都指向较旧的完整备份。

当我尝试生成 SSMS 尝试执行的还原脚本时,奇怪的是我得到了与工具提示相同的错误,并且它不会给我脚本:

恢复脚本

仔细检查后,当我选择所有备份(包括完整备份)时,SSMS 会自动删除完整备份并仅加载要还原的事务日志备份。我真的认为有一个损坏的备份链让 SSMS 感到困惑:

仅事务日志备份

如果我只选择要恢复的完整备份,那么它可以让我单击脚本按钮,这就是完整备份本身的脚本:

USE [master]
RESTORE DATABASE [MyDatabase] FROM  DISK = N'P:\MyDatabase\MyDatabase_backup_2021_09_16_223001_3540051.bak' WITH  FILE = 1,  NOUNLOAD,  STATS = 5

此外,我的维护计划未设置为“仅复制备份”:

完整备份维护计划

作为参考,这里是完整备份维护计划中的数据库之一的 T-SQL 脚本:

BACKUP DATABASE [master] TO  DISK = N'\\OurDomain\Shares\SQL Backups\Full Backups\master\master_backup_2021_09_19_004931_6111907.bak' WITH  RETAINDAYS = 14, NOFORMAT, NOINIT,  NAME = N'master_backup_2021_09_19_004931_6111907', SKIP, REWIND, NOUNLOAD, COMPRESSION,  STATS = 10

如果我手动编写完整备份的还原以及在该完整备份之后发生的最接近事务日志备份的脚本,它会很好地还原完整备份并将数据库保留在其中,NORECOVERY但事务日志备份失败并出现以下错误:

手动脚本还原失败

这些是我编写的手动脚本:

USE [master]

RESTORE DATABASE [MyDatabase] 
FROM DISK = N'P:\MyDatabase\MyDatabase_backup_2021_09_16_223001_3540051.bak'
WITH NORECOVERY;

RESTORE LOG [MyDatabase]
FROM DISK = N'P:\MyDatabase\MyDatabase_backup_2021_09_16_223001_4008446.trn'
WITH RECOVERY;

奇怪的是,如果我尝试恢复在完全备份之前发生的最近的事务日志备份,我会得到完全相同的错误消息,引用完全相同的 LSN。所以就像我的事务日志备份没有遵循与我的完整备份相同的备份链?

我能想到的唯一其他相关信息是这些备份维护计划最初是在 SQL Server 2016 实例上设置的。该实例的服务器崩溃了,我们使用 SQL Server 2019 实例启动了一个全新的服务器。我将所有用户和系统数据库从备份(讽刺地)还原到新的 SQL Server 2019 实例。(我必须首先在 2016 实例上恢复系统数据库,并在它允许我在新的 2019 服务器上恢复它们​​之前进行就地升级。)我无法成功恢复到新服务器的唯一数据库是master数据库。到目前为止,其他一切似乎都运行良好。

sql-server backup
  • 2 个回答
  • 331 Views
Martin Hope
J.D.
Asked: 2021-01-08 18:27:53 +0800 CST

STRING_SPLIT() 函数的结果是否以确定的顺序返回?

  • 5

我需要拆分以逗号分隔的字符串,对其进行操作,然后将其连接回单个字符串,保留数据的原始顺序(如果可能)。

例如,采用这样的CREATE TABLE语句(作为字符串)的列定义列表'BrentOzarColumn INTEGER, PaulWhiteColumn DATETIME, ErikDarlingColumn VARCHAR(100)'。我想将逗号分隔的列表拆分为一个结果集,例如使用 SQL Server 的内置函数,如下所示STRING_SPLIT():SELECT TRIM([Value]) AS CoolDataPeople FROM STRING_SPLIT('BrentOzarColumn INTEGER, PaulWhiteColumn DATETIME, ErikDarlingColumn VARCHAR(100)', ',')

在不指定ORDER BY子句的情况下,这会重复产生(通过巧合?)以下结果,这些结果似乎按照与字符串中相同的顺序进行排序:

结果

一旦我得到了上面的结果集,我想对每一行应用一些额外的字符串操作(比如附加一些常量文本),然后用一个函数连接每一行,比如STRING_AGG()(再见天数STUFF ... FOR XML PATH:),顺序与原始字符串。所以我的最终结果的一个例子可能是'BrentOzarColumn INTEGER SQLROX, PaulWhiteColumn DATETIME SQLROX, ErikDarlingColumn VARCHAR(100) SQLROX'.

最终我的问题是:函数的结果是否STRING_SPLIT()以确定的顺序返回?我知道没有ORDER BY子句,从 a Tableor之类的数据集中选择时不能保证排序View,但想知道函数是否有区别?

当我输入这个时,我有一种预感,答案是否定的,排序不是确定性的,因此我不能保证结果的顺序。此外,我敢打赌,我在结果之上运行的每个函数都可能添加了额外的不确定性,尤其是当我将它们与STRING_AGG(). (无论答案如何,我都感谢您的帮助,你们都是很酷的数据人。;)

sql-server sql-server-2017
  • 1 个回答
  • 825 Views
Martin Hope
J.D.
Asked: 2020-11-12 14:22:12 +0800 CST

快照前和快照后复制脚本未执行且无错误

  • 3

我在服务器 1 上设置了快照复制发布。服务器 2 订阅了服务器 1 上的发布。数据复制成功。

服务器 2 的订阅服务器的分发服务器代理和代理作业在服务器 1(分发服务器数据库所在的位置)上运行。

我在服务器 2 上创建了一个存储过程,以在服务器 2 的订户数据库上删除(预复制)和创建(复制后)模式绑定实体。(我过去成功地做到了这一点,因为如果订阅数据库中存在绑定到复制实体的模式的实体,快照复制可能会停止。)

我还创建了一个脚本,该脚本通过链接服务器从服务器 1 到服务器 2 执行此存储过程。(我已验证链接服务器设置正确,我可以从服务器查询数据并通过链接服务器手动执行存储过程1 到服务器 2。)我已将此脚本添加到快照发布的“快照”属性中: 在此处输入图像描述

最初,我在快照代理作业中收到错误,因为我的快照代理没有对脚本中路径的文件共享访问权限,但我添加了该帐户,然后错误消失了,快照作业现在成功完成。

但是 SQL 脚本中的实体不会被删除或创建,而且我在任何地方都没有看到错误。我还尝试将之前和之后的脚本文件移动到服务器 1 本地的文件夹共享并使用 UNC 路径(与屏幕截图中的网络路径相反)引用它,但行为仍然没有变化。

我已经使用以下代码使用非常简单的测试更新了 TEST.sql 脚本:

INSERT INTO DatabaseA.dbo.Table1 (Field1) -- DatabaseA is on Server1, so it should insert to the local table
SELECT 'Test' AS Field1

当我重新运行快照代理时,它仍然成功运行,但表没有插入(在服务器 1 上)。

为什么我的前置脚本和后置脚本无法运行,但我也没有收到任何错误?

(我在服务器 1 上还有另一个事务复制发布,它将数据同步到与快照复制相同的数据库中的服务器 2。但即使我在服务器 1 上的事务性发布,我仍然没有收到任何错误,并且 SQL 没有执行。)

编辑:我也只是尝试将脚本文件移动到服务器 1 的本地文件夹,授予快照代理对该文件夹和脚本文件的读取权限,然后重新运行快照代理,但仍然没有。没有执行脚本,也没有错误。

但有趣的是,如果我手动修改订阅代理作业本身并添加一个步骤来执行相同的确切 SQL 查询,它确实可以工作。

我还注意到 SQL 代理作业在不同的 SQL 帐户“sqlmin”下运行,然后我期望某些步骤(我创建的新步骤,或者称为“快照代理启动消息”的作业的第一步 - 我猜是因为这些步骤不是t 类型为“REPL-Distributor”)。但是其他预先存在的步骤作为我指定的 SQL 代理执行,即“DBReplication”。我知道的“sqlmin”帐户在服务器 1 和服务器 2 上都具有非常小的 SQL 权限,这可能是为什么当我没有执行复制前和复制后脚本的原因(但我也没有在任何地方收到错误)在快照发布 - 快照属性的前置和后置字段上设置脚本?

还有关于分发者帐户(也是我的快照代理帐户)的其他详细信息:分发者是一个 Windows AD 帐户,在服务器 1 和服务器 2 上都有 SQL LOGIN,并且在复制的源和目标中都具有 db_owner 的 SQL 角色数据库以及分发数据库(位于服务器 1 上)上的 db_owner。

sql-server replication
  • 2 个回答
  • 596 Views
Martin Hope
J.D.
Asked: 2020-10-09 07:28:37 +0800 CST

为什么我的执行计划显示在使用专门使用非聚集索引的索引提示时正在发生聚集索引扫描?

  • 1

幕后故事:

我有一个具有以下结构的表:

CREATE TABLE WideTable1
(
    BoringColumn1,
    BoringColumn2,
    CellPhoneNumberColumn Phone(VARCHAR(20)), -- User-defined types, see below
    PagerPhoneNumberColumn Phone(VARCHAR(20)), -- User-defined types, see below
    IsActive YN(CHAR(1)), -- User-defined types, see below
    BoringColumn3,
    ...
    BoringColumn350
)

使用此表的原始查询是在 CellPhoneNumberColumn 和 PagerPhoneNumber 上执行一些 SQL 函数,然后稍后将这些函数的输出用作另一个查询中的谓词。NULLIF(LTRIM(ISNULL(CellPhoneNumberColumn, PagerPhoneNumberColumn)))就是一个例子。

这些列也是所有用户定义的类型,在这种情况下 CellPhoneNumberColumn 和 PagerPhoneNumberColumn 被定义为 UDT Phone(VARCHAR(20)),因此它们的基础数据类型是VARCHAR(20)。IsActive 被定义为 YN(CHAR(1)) 所以它实际上是一个 CHAR(1)。

此外更复杂的是,这个表/数据库的排序规则是Latin1_General_BIN.

长话短说,最初的消费查询遇到了基数估计问题。为了缓解这个问题,我在上面的列上创建了一个索引视图,并使用以下定义将 SQL 函数应用于它们(*注意我没有创建这个原始逻辑,只是试图修复它的性能):

CREATE VIEW PhoneNumbersNormalized WITH SCHEMABINDING AS

SELECT 
    NULLIF(LTRIM(ISNULL(CAST(CellPhoneNumberColumn AS VARCHAR(20)), CAST(PagerPhoneNumberColumn AS VARCHAR(20)))) AS Cell,
    SUM(CASE WHEN CAST(IsActive AS CHAR(1)) = 'Y'THEN 1 ELSE 0 END) AS IsActive 
FROM dbo.WideTable1
GROUP BY NULLIF(LTRIM(ISNULL(CAST(CellPhoneNumberColumn AS VARCHAR(20)), CAST(PagerPhoneNumberColumn AS VARCHAR(20)))) 

我还在索引视图 PhoneNumbersNormalized 上创建了以下索引:

CREATE UNIQUE CLUSTERED INDEX IXV_PhoneNumbersNormalized_Cell ON dbo.PhoneNumbersNormalized(Cell)
CREATE NONCLUSTERED INDEX IXV_NC_PhoneNumbersNormalized_Cell_IsActive ON  dbo.PhoneNumbersNormalized(Cell, IsActive)

问题: 当我从包含实际执行计划的索引视图 PhoneNumbersNormalized 中进行选择时,我注意到执行计划特别提到了原始基础表 WideTable1 作为数据的来源。

此外,如果我从索引视图中选择 PhoneNumbersNormalized 并IXV_NC_PhoneNumbersNormalized_PhoneNumber_IsActive在执行计划上方创建的非聚集索引上显示索引提示,则没有提及正在使用此非聚集索引,而是说它正在执行聚集索引扫描(注意我混淆了原始表名,它在我的服务器上实际上并不称为 WideTable1): 执行计划

粘贴的执行计划: https ://www.brentozar.com/pastetheplan/?id=HJytxh2UP

为什么执行计划总是显示原始基础表而不是索引视图,并且总是在基础表上使用聚集索引,即使我对索引视图的选择查询使用索引提示强制使用非聚集索引?

sql-server sql-server-2016
  • 1 个回答
  • 299 Views
Martin Hope
J.D.
Asked: 2020-10-07 05:27:55 +0800 CST

当这些 UDDT 的字段用作谓词时,用户定义的数据类型是否总是会导致发生隐式转换?

  • 0

我有一个数据库(来自供应商应用程序),由于某种未知原因,几乎每一列都有一个 UDDT,即使 UDDT 在逻辑上与其实现的基础类型相同。例如,此数据库中的列可能是 UDDT bTinyInt(TinyInt)。

此数据库中的两个表具有共享完全相同的 UDDT 的列。例如TableA.Field1是 类型bVarchar(VARCHAR(10))并且TableB.Field2也是bVarchar(VARCHAR(10))。

当我通过上述字段将这两个表连接在一起时,我注意到执行计划中的警告指出基数问题,因为这些字段被隐式转换为VARCHAR(MAX).

UDDT 在用作谓词时是否总是会隐式转换,即使在比较相同的 UDDT 时也是如此?

也不确定它是否也很重要,但是这两个表所属的数据库是 collat​​ion Latin1_General_BIN。

sql-server sql-server-2016
  • 2 个回答
  • 85 Views
Martin Hope
J.D.
Asked: 2020-09-23 15:20:51 +0800 CST

是否可以为数据与单个数据库中的实体指定不同的排序规则?

  • 0

我有一个带有区分大小写排序规则的数据库,因为其中的数据在其使用方式的上下文中应该被视为区分大小写。

同一数据库中的实体及其列名不需要区分大小写,我们希望它们不用于查询目的。

是否可以将数据本身保持为区分大小写但允许实体在同一数据库中不区分大小写?

sql-server sql-server-2016
  • 1 个回答
  • 437 Views
Martin Hope
J.D.
Asked: 2020-07-17 06:52:05 +0800 CST

使用 FORCESEEK 时收到“由于此查询中定义的提示,查询处理器无法生成查询计划”但可以使用 FORCESCAN?

  • 0

我有一个相当大的表(5 亿行,30 列宽,总共大约 130 GB 的数据)。该表中的一列是 DateTime 数据类型,我需要在某个日期范围内重复从该表中选择记录。对我来说似乎是过滤索引的好候选人。

这是我的过滤索引:

CREATE NONCLUSTERED INDEX IX_Filtered_Table1_DateField1 
ON Table1 (DateField1, PrimaryKeyField) 
WHERE (DateField1 >= '2/24/20' AND DateField1 < '4/14/20')

这是我的查询:

DECLARE @MinPrimaryKeyId BIGINT = 2854868995

SELECT TOP 500000 PrimaryKeyField
INTO #Results
FROM Table1 WITH(INDEX(IX_Filtered_Table1_DateField1))
WHERE DateField1 >= '2/24/20'
and DateField1 < '4/14/20'
and PrimaryKeyField > @MinPrimaryKeyId
ORDER BY PrimaryKeyField ASC

在检查执行计划时,我注意到它使用的是我的过滤索引,但它默认为索引扫描操作而不是索引搜索。

如果我尝试使用 FORCESEEK 查询提示(除了我的索引提示),我会收到经典错误:

由于此查询中定义的提示,查询处理器无法生成查询计划

为什么查询处理器无法在该索引上使用 Seek 操作生成执行计划,但它可以使用它执行 Scan 操作?(如果我用 FORCESCAN 切换我的 FORCESEEK 查询提示,它就可以工作,我知道这与在这里根本不使用提示没有什么不同。)

sql-server sql-server-2016
  • 1 个回答
  • 737 Views
Martin Hope
J.D.
Asked: 2020-06-26 09:09:10 +0800 CST

向表中添加列存储索引会影响在同一表上使用行存储索引的查询的读取性能吗?

  • 5

我正在对大约 5 亿行的单个表上的列存储索引进行一些测试。聚合查询的性能提升非常棒(以前运行大约需要 2 分钟的查询现在运行在 0 秒内即可聚合整个表)。

但我也注意到另一个利用在同一张表上的现有行存储索引上查找的测试查询现在的运行速度是之前创建列存储索引之前的 4 倍。我可以反复演示删除列存储索引时,行存储查询在 5 秒内运行,并且通过在列存储索引中添加回行存储查询在 20 秒内运行。

我一直关注行存储索引查询的实际执行计划,无论列存储索引是否存在,这两种情况几乎完全相同。(它在这两种情况下都使用行存储索引。)

行存储测试查询是:

SELECT *
INTO #TEMP
FROM Table1 WITH (FORCESEEK)
WHERE IntField1 = 571
    AND DateField1 >= '6/01/2020'

此查询中使用的行存储索引是:CREATE NONCLUSTERED INDEX IX_Table1_1 ON Table1 (IntField1, DateField1) INCLUDE (IntField2)

列存储测试查询是:

SELECT COUNT(DISTINCT IntField2) AS IntField2_UniqueCount, COUNT(1) AS RowCount
FROM Table1
WHERE IntField1 = 571 -- Some other test columnstore queries also don't use any WHERE predicates on this table
    AND DateField1 >= '1/1/2019' 

列存储索引为:CREATE NONCLUSTERED COLUMNSTORE INDEX IX_Table1_2 ON Table1 (IntField2, IntField1, DateField1)

这是我创建列存储索引之前行存储索引查询的执行计划: 执行计划 - 行存储索引 - 列存储前索引创建

这是我创建列存储索引后行存储索引查询的执行计划: 执行计划 - 行存储索引 - 列存储后索引创建

我注意到这两个计划之间的唯一区别是,在创建列存储索引后,排序操作的警告消失了,而键查找和表插入 (#TEMP) 运算符花费的时间要长得多。

这是带有警告的排序操作信息(在创建列存储索引之前): 排序操作 - 警告

这是没有警告的排序操作信息(在创建列存储索引之后): 排序操作

我会认为在这两种情况下专门利用相同行存储索引和执行计划的读取查询在每次运行时应该具有大致相同的性能,而不管该表上存在哪些其他索引。这里给出了什么?

编辑:这是创建索引之前的 TIME 和 IO 统计信息: 统计信息 - 创建列存储索引之前

以下是创建列存储索引后的统计信息: 统计信息 - 创建列存储索引后

sql-server index
  • 1 个回答
  • 612 Views
Martin Hope
J.D.
Asked: 2020-06-12 09:56:16 +0800 CST

我可以采取哪些步骤来确定我的服务器的内存配置是否不足?

  • 4

我的服务器正在运行 SQL Server 2016。该环境的工作负载相当高,全天有大量写入事务和读取数据。我有一种预感,服务器没有配置足够的内存,我想深入研究一下,看看是不是这样。确定服务器上可用内存量是否以及产生多少争用的最佳方法是什么?

我确实查看了 DMV sys.dm_os_wait_stats,当按 waiting_tasks_count desc 排序时,前两种等待类型是“MEMORY_ALLOCATION_EXT”和“RESERVED_MEMORY_ALLOCATION_EXT”,比任何其他等待类型任务计数都大一个数量级。还有其他地方我可以检查内存压力或争用吗?

编辑:此服务器上所有数据库的总大小为 3 TB,具有大部分事务的主数据库为 2 TB,服务器上的 RAM 总量为 32 GB。

编辑 2:这是一天中的延迟写入/第二次性能计数器结果: 每秒延迟写入 - PerfMon 计数器

sql-server sql-server-2016
  • 1 个回答
  • 2855 Views
Martin Hope
J.D.
Asked: 2020-06-10 14:34:13 +0800 CST

如果行存储索引存储在 b 树数据结构中,列存储索引使用哪种数据结构?[复制]

  • 1
这个问题在这里已经有了答案:
列存储索引的结构是什么? (1 个回答)
2年前关闭。

我对如何存储常规行存储索引的理解是在一种 b-tree 数据结构中,但我想知道由于列存储索引的不同性质,使用什么类型的底层数据结构?

sql-server index
  • 1 个回答
  • 281 Views
Martin Hope
J.D.
Asked: 2020-05-02 20:09:34 +0800 CST

是否可以使用从已恢复的过期服务器时间点快照开始的数据库备份来恢复数据库?

  • 1

如果我定期备份 SQL 实例和数据库所在的整个服务器,并将其还原到另一台机器上,我可以使用在生成完整服务器快照后(在原始服务器上)发生的数据库备份,将新的恢复服务器最新?

我需要哪些类型的数据库备份才能做到这一点?我猜如果我有当前数据库的完整备份就足够了,但是如果我上次的完整备份与服务器快照一样旧(甚至更早),我可以使用该完整备份 + 任何差异,事务日志等在该完整备份之后进行的备份,以使我在新恢复的服务器上的服务器快照恢复最新?

示例(为简单起见,我们假设每个备份都立即完成):

服务器 1 在每天下午 5:30 拍摄完整的服务器时间点快照。

服务器 1 上的数据库 A 在每天晚上 11:30 进行每晚的完整备份。

数据库 A 还具有全天每小时进行的例行差异备份。

数据库 A 还具有全天每 15 分钟备份一次的事务日志。

场景一:

服务器 1 在晚上 11:50 崩溃。

从当天早些时候下午 5:30 开始,服务器 2 从服务器 1 的完整服务器时间点快照备份中恢复。

我们能否使用从晚上 11:30(崩溃前 20 分钟)开始的数据库 A 的完整备份(从服务器 1)将数据库恢复到晚上 11:30 时的状态,然后使用晚上 11:45 的事务日志备份使数据库尽可能最新(在服务器 2 上)?

场景二:

服务器 1 在晚上 11:20 崩溃。

从当天早些时候下午 5:30 开始,服务器 2 从服务器 1 的完整服务器时间点快照备份中恢复。

我们可以使用前一天晚上 11:30 的数据库 A 的完整备份(因为我们今天在崩溃之前还没有进行备份),然后是前一天晚上 11:30 之间的所有每小时差异备份,直到晚上 11 点,然后是 11:15 的事务日志备份,以使数据库尽可能更新(在服务器 2 上)?

在上述任一情况下是否有更有效的恢复方式和/或数据库备份类型和频率的更好处理方式?

sql-server backup
  • 2 个回答
  • 87 Views
Martin Hope
J.D.
Asked: 2020-04-30 13:56:31 +0800 CST

是否可以为 AlwaysOn 可用性组中的数据库设置多个 RW 副本?

  • 0

是否可以在不同服务器上拥有 AlwaysOn 可用性组数据库的多个 RW 副本?(即双向复制,以便多个服务器可以写入同一个数据库。)

sql-server replication
  • 1 个回答
  • 104 Views

Sidebar

Stats

  • 问题 205573
  • 回答 270741
  • 最佳答案 135370
  • 用户 68524
  • 热门
  • 回答
  • Marko Smith

    连接到 PostgreSQL 服务器:致命:主机没有 pg_hba.conf 条目

    • 12 个回答
  • Marko Smith

    如何让sqlplus的输出出现在一行中?

    • 3 个回答
  • Marko Smith

    选择具有最大日期或最晚日期的日期

    • 3 个回答
  • Marko Smith

    如何列出 PostgreSQL 中的所有模式?

    • 4 个回答
  • Marko Smith

    列出指定表的所有列

    • 5 个回答
  • Marko Smith

    如何在不修改我自己的 tnsnames.ora 的情况下使用 sqlplus 连接到位于另一台主机上的 Oracle 数据库

    • 4 个回答
  • Marko Smith

    你如何mysqldump特定的表?

    • 4 个回答
  • Marko Smith

    使用 psql 列出数据库权限

    • 10 个回答
  • Marko Smith

    如何从 PostgreSQL 中的选择查询中将值插入表中?

    • 4 个回答
  • Marko Smith

    如何使用 psql 列出所有数据库和表?

    • 7 个回答
  • Martin Hope
    Jin 连接到 PostgreSQL 服务器:致命:主机没有 pg_hba.conf 条目 2014-12-02 02:54:58 +0800 CST
  • Martin Hope
    Stéphane 如何列出 PostgreSQL 中的所有模式? 2013-04-16 11:19:16 +0800 CST
  • Martin Hope
    Mike Walsh 为什么事务日志不断增长或空间不足? 2012-12-05 18:11:22 +0800 CST
  • Martin Hope
    Stephane Rolland 列出指定表的所有列 2012-08-14 04:44:44 +0800 CST
  • Martin Hope
    haxney MySQL 能否合理地对数十亿行执行查询? 2012-07-03 11:36:13 +0800 CST
  • Martin Hope
    qazwsx 如何监控大型 .sql 文件的导入进度? 2012-05-03 08:54:41 +0800 CST
  • Martin Hope
    markdorison 你如何mysqldump特定的表? 2011-12-17 12:39:37 +0800 CST
  • Martin Hope
    Jonas 如何使用 psql 对 SQL 查询进行计时? 2011-06-04 02:22:54 +0800 CST
  • Martin Hope
    Jonas 如何从 PostgreSQL 中的选择查询中将值插入表中? 2011-05-28 00:33:05 +0800 CST
  • Martin Hope
    Jonas 如何使用 psql 列出所有数据库和表? 2011-02-18 00:45:49 +0800 CST

热门标签

sql-server mysql postgresql sql-server-2014 sql-server-2016 oracle sql-server-2008 database-design query-performance sql-server-2017

Explore

  • 主页
  • 问题
    • 最新
    • 热门
  • 标签
  • 帮助

Footer

AskOverflow.Dev

关于我们

  • 关于我们
  • 联系我们

Legal Stuff

  • Privacy Policy

Language

  • Pt
  • Server
  • Unix

© 2023 AskOverflow.DEV All Rights Reserve