AskOverflow.Dev

AskOverflow.Dev Logo AskOverflow.Dev Logo

AskOverflow.Dev Navigation

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

Mobile menu

Close
  • 主页
  • 系统&网络
    • 最新
    • 热门
    • 标签
  • Ubuntu
    • 最新
    • 热门
    • 标签
  • Unix
    • 最新
    • 标签
  • DBA
    • 最新
    • 标签
  • Computer
    • 最新
    • 标签
主页

dba

Martin Hope
Sidney
Asked: 2023-03-21 02:53:01 +0800 CST

创建索引然后删除它是否会将数据库返回到索引创建前的状态?

  • 14

我正在测试一些索引,并想对哪些索引执行得更好进行一些 AB 测试(主要是索引中字段的顺序和指定的其他字段)。

我有一个正在测试的数据库的备份,但该备份需要很长时间才能恢复。我更愿意只创建索引 foo,收集性能指标,然后删除 foo 以将数据库返回到索引前状态并创建索引 bar。这是创建索引的工作方式,还是创建索引会以某种删除索引无法撤消的方式更改表?

sql-server
  • 4 个回答
  • 1076 Views
Martin Hope
John K. N.
Asked: 2023-02-17 06:09:38 +0800 CST

在列列表中带有 , * 的 SELECT 语句比没有 * 的相同语句更快

  • 15

情况

当使用包含一组已定义列的 SELECT 语句查询数据库时,大约 21 秒内会收到结果。

, *如果在定义的列集列表末尾有一个额外的星号 ( ),则查询将在 2 秒内返回结果。

查询执行计划

执行计划有很大不同。

您可以使用 PasteThePlan 中的链接找到好的实际查询执行计划和坏的实际查询执行计划。

列列表中包含 , * 的语句(末尾)


            SELECT    -- DISTINCT -- 27.04.2020
                'SchuelerKlasse' AS EcoQuery,
                VX_PERSON.PER_MAN_ID, VX_PERSON.PER_ID, VX_PERSON.PER_NAME, VX_PERSON.PER_VORNAME, VX_PERSON.PER_LB_PER_ID, 
                VX_PERSON.PER_GESCHLECHT, VX_PERSON.PER_GEBURTSDATUM, VX_PERSON.PER_TELP, VX_PERSON.PER_MAILP, VX_PERSON.PER_NATP, VX_PERSON.PER_VERSICHERTENNUMMER, VX_PERSON.PER_LAND,
                VX_ADRESSE.ADR_STRASSE, VX_ADRESSE.ADR_PLZ, VX_ADRESSE.ADR_ORT,
                VX_KLASSE.KL_CODE, VX_KLASSE.KL_BEZEICHNUNG,
                VX_KLASSEABSCHNITTSCHUELER.KAS_ANMELDE_STATUS, 
                VX_KLASSEABSCHNITTSCHUELER.KAS_ANMELDETYP, VX_KLASSEABSCHNITTSCHUELER.KAS_ABSCHNITTSNR,
                VX_KLASSE_ZEITRAUM.KLZ_IS_ABSCHLUSSKLASSE, VX_KLASSE_ZEITRAUM.KLZ_ZR_NR,
                VX_ZEITRAUM.ZR_BEGINN, VX_ZEITRAUM.ZR_ENDE
                ,'' AS FA_CODE
                ,'' AS FA_BEZ_STP, '' AS FA_BEZ_STP_LANG
                , '' AS EcoOrig_FA_CODE, '' AS EcoOrig_FA_BEZ_STP, '' AS EcoOrig_FA_BEZ_STP_LANG
                , VX_ANGEBOT.ANG_BEGINN
            
 ,* 

            FROM 
                ECOLST.VX_KLASSE_ZEITRAUM, 
                ECOLST.VX_PERSON, 
                ECOLST.VX_KLASSE, 
                ECOLST.VX_KLASSEABSCHNITTSCHUELER, 
                ECOLST.VX_ZEITRAUM, 
                ECOLST.VX_ADRESSE 
                , ECOSYS.T_KLASSE
                , ECOLST.VX_ANGEBOT

            WHERE  
                    VX_KLASSE_ZEITRAUM.klz_kl_id = VX_KLASSE.kl_id 
                AND VX_KLASSE_ZEITRAUM.klz_zr_id = VX_ZEITRAUM.zr_id 
                AND VX_KLASSEABSCHNITTSCHUELER.kas_ang_id = VX_KLASSE.kl_ang_id 
                AND VX_KLASSEABSCHNITTSCHUELER.kas_zr_id = VX_ZEITRAUM.zr_id 
                AND VX_KLASSEABSCHNITTSCHUELER.kas_per_id = VX_PERSON.per_id 
                AND VX_KLASSEABSCHNITTSCHUELER.kas_kl_id = VX_KLASSE.kl_id 
                AND VX_KLASSEABSCHNITTSCHUELER.KAS_ANMELDE_STATUS LIKE 'De%'  -- LIKE 'Definitiv%'
                AND VX_PERSON.per_id = VX_ADRESSE.adr_per_id 
                AND VX_PERSON.per_man_id = VX_KLASSE.kl_man_id
                AND VX_KLASSE.KL_ANG_ID = VX_ANGEBOT.ANG_ID
                AND VX_KLASSE.KL_MAN_ID = 15 
                AND VX_KLASSE.KL_ID = T_KLASSE.KL_ID
                AND T_KLASSE.KL_STATUS_ID = 491   -- d.h. TS_CODE.CODE_UP_BEZEICHNUNG = 'AKTIV'
            

                AND VX_KLASSE.KL_KLASSENTYP_ID IN (742,743,1235,1926,2075,2076,2078,2079,2080,2081,2086,2103,2118,2119,2122,2152,2252,2308,2416)
        

                AND VX_PERSON.PER_NP = 1   -- Natürliche Person
                AND LEN(LTRIM(RTRIM(VX_PERSON.PER_VORNAME))) > 0        -- TRIM() kann erst ab SQL Server 2017 verwendet werden
                AND LEN(LTRIM(RTRIM(VX_PERSON.PER_NAME))) > 0           -- TRIM() kann erst ab SQL Server 2017 verwendet werden
        
 AND VX_ZEITRAUM.zr_beginn <= CONVERT(DATETIME, '20.05.2023', 104) 
 AND VX_ZEITRAUM.zr_ende   >= CONVERT(DATETIME, '14.02.2023', 104) 
 AND VX_PERSON.per_man_id IN ( 15 ) 

                --AND VX_Person.PER_ID IN  (233777,233779)
        

问题

*一般建议在定义列列表时不要使用,但在我的例子中,, *在末尾添加到列列表,可以显着加快查询速度。(从 21 秒减少到 2 秒)

实际执行计划中没有缺失索引建议。

, *我认为这与在语句中使用时返回的特定列有关,这些列可能包含在查询优化器认为有用的索引中,但我不确定如何查明这些列。

  1. 为了说服 SQL Server 运行不包含, *列列表的执行不佳的语句,使用与包含列列表中的附加项的性能语句类似的计划,我必须创建哪些索引?, *

  2. 我是否必须分析良好执行计划中使用的所有索引并创建缩减索引(省略某些列)以便查询优化器考虑对语句使用类似的良好, *执行计划而不需要额外的?


根据建议尝试解决方案

  1. OPTION (MIN_GRANT_PERCENT = 10, MAX_GRANT_PERCENT = 15)

    应用上述解决方案仅提供了大约 1 小时的临时性能提升。之后查询恢复到错误的执行计划。我不知道为什么...

  2. 数据库兼容级别

    ,*使用以下命令将数据库的兼容级别向下更改为 110 (SQL Server 2012),导致上述查询的性能不断提高,而无需在列列表中添加。

    USE [master]
    GO
    ALTER DATABASE [ECOWEBBSP] SET COMPATIBILITY_LEVEL = 110
    GO
    

    兼容级别为 110 的查询执行计划表明,查询优化器在检索数据时选择了一种完全不同的方法,并且在分配正确的内存量 (110 MB) 方面没有任何问题。

跟进问题

将兼容级别设置为 110 是我唯一的选择吗?

额外反馈

Erik 的回答中提到的Ominous Function是由视图中的fi_kla_is_abschlussklasse列触发的。基础表在检索数据时调用标量值函数。该函数本身返回 0 或 1,具体取决于学生是在毕业班 (1) 还是不在毕业班 (0)。VX_KLASSE_ZEITRAUM.KLZ_IS_ABSCHLUSSKLASSEECOLST.VX_KLASSE_ZEITRAUM

但是,在兼容级别设置为 110 (SQL Server 2012) 的情况下运行时,该函数似乎对查询持续时间的影响不大。有关详细信息,请参阅兼容级别为 110 的查询执行计划。

sql-server
  • 1 个回答
  • 1149 Views
Martin Hope
Chad Baldwin
Asked: 2023-01-31 12:24:16 +0800 CST

如果禁用非聚集索引,是否仍使用统计信息?

  • 15

tl; dr - 如标题所述 - 如果我禁用表上的非聚集索引,是否仍使用该索引的链接统计信息?


我知道有很多关于“删除与禁用索引”的问题......但我找不到专门涵盖统计信息的问题。

我知道统计数据没有改变或改变(至少这是我从 MS 文档中收集到的)。但我的问题是统计数据是否仍在使用。


作为背景,我正在从事一个大型索引调优项目。它涉及在数百个具有不同工作负载模式的相同数据库中添加/删除索引。总共有超过 200 万个索引。

我的第一步是删除所有“未使用”的索引。但是,我没有放弃它们,而是考虑禁用它们以保留定义。这将允许我在表中记录任何禁用的索引的实例、数据库、对象 ID 和索引名称/ID。如果之后性能开始下降,可以重新启用(重建)索引。

但是,如果已禁用索引的统计信息仍用于生成计划...那么禁用它们不会产生与删除它们相同的性能影响。如果是这种情况,那么禁用索引就不是“真正的”性能影响测试,如果禁用的索引最终被删除,我就有引入性能问题的风险。

sql-server
  • 1 个回答
  • 743 Views
Martin Hope
Joe Obbish
Asked: 2022-11-19 13:13:44 +0800 CST

为什么在使用表变量时,一个简单的本机编译存储过程会耗尽内存?

  • 18

我的 SQL Server 版本是 SQL Server 2019 (RTM-CU18)。以下重现代码需要创建一个内存文件组。对于后续的任何人,请记住内存中的文件组一旦创建就不能从数据库中删除。

我有一个简单的内存表,我在其中插入 1 - 1200 之间的整数:

DROP TABLE IF EXISTS [dbo].[InMem];

CREATE TABLE [dbo].[InMem] (
    i [int] NOT NULL,
    CONSTRAINT [PK_InMem]  PRIMARY KEY NONCLUSTERED (i ASC)
) WITH ( MEMORY_OPTIMIZED = ON , DURABILITY = SCHEMA_ONLY );

INSERT INTO [dbo].[InMem]
SELECT TOP (1200) ROW_NUMBER() OVER (ORDER BY (SELECT NULL))
FROM master..spt_values t1
CROSS JOIN master..spt_values t2;

我还有以下本机编译的存储过程:

GO

CREATE OR ALTER PROCEDURE p1
WITH NATIVE_COMPILATION, SCHEMABINDING 
AS
BEGIN ATOMIC WITH (TRANSACTION ISOLATION LEVEL = SNAPSHOT, LANGUAGE = N'us_english')
    SELECT c1.i, c2.i, c3.i
    FROM dbo.[InMem] c1
    CROSS JOIN dbo.[InMem] c2
    CROSS JOIN dbo.[InMem] c3
    WHERE c1.i + c2.i + c3.i = 3600;
END;

GO  

该过程在执行时返回一行。在我的机器上大约需要 32 秒才能完成。在执行时,我无法观察到内存使用方面的任何异常行为。

我可以创建一个类似的表类型:

CREATE TYPE [dbo].[InMemType] AS TABLE(
i [int] NOT NULL,
INDEX [ix_WordBitMap] NONCLUSTERED (i ASC)
) WITH ( MEMORY_OPTIMIZED = ON );

以及相同的存储过程,但改用表类型:

GO

CREATE OR ALTER PROCEDURE p2 (@t dbo.[InMemType] READONLY)
WITH NATIVE_COMPILATION, SCHEMABINDING 
AS
BEGIN ATOMIC WITH (TRANSACTION ISOLATION LEVEL = SNAPSHOT, LANGUAGE = N'us_english')
    SELECT c1.i, c2.i, c3.i
    FROM @t c1
    CROSS JOIN @t c2
    CROSS JOIN @t c3
    WHERE c1.i + c2.i + c3.i = 3600;
END;

GO

新存储过程在大约一分钟后抛出错误:

消息 701,级别 17,状态 154,过程 p2,第 6 行 [批处理起始行 57] 资源池“默认”中的系统内存不足,无法运行此查询。

sys.dm_os_memory_clerks当程序执行时,我可以通过查询dmv看到 MEMORYCLERK_XTP 内存管理员使用的内存量增加到数据库的大约 2800 MB 。根据sys.dm_db_xtp_memory_consumersDMV,几乎所有的内存使用似乎都来自“64K 页面池”消费者:

在此处输入图像描述

在此处输入图像描述

作为参考,这里是我如何执行新存储过程的。它使用与表相同的 1200 行:

DECLARE @t dbo.[InMemType];

INSERT INTO @t (i)
SELECT i
from [dbo].[InMem];

EXEC p2 @t;

生成的查询计划是一个没有阻塞运算符的简单嵌套循环计划。根据请求,这是第二个存储过程的估计查询计划。

我不明白为什么当我使用表值参数时,这样的查询的内存使用量会增长到超过 2 GB。我已经阅读了各种文档和内存中 OLTP 白皮书,但找不到任何关于此行为的参考。

使用 ETW 跟踪,我可以看到第一个过程将其大部分 cpu 时间用于调用hkengine!HkCursorHeapGetNext,而第二个过程将其大部分 cpu 时间用于调用hkengine!HkCursorRangeGetNext. 我还可以获得这两个程序的 C 源代码。第一个程序在这里,第二个程序有内存问题,在这里。但是,我不知道如何阅读 C 代码,所以我不知道如何进一步调查。

为什么在对表值参数执行嵌套循环时,一个简单的本机编译存储过程会使用超过 2 GB 的内存?当我在存储过程之外运行查询时,也会出现此问题。

sql-server
  • 1 个回答
  • 646 Views
Martin Hope
Brent Ozar
Asked: 2022-11-04 08:38:35 +0800 CST

为什么 SQL Server 安装程序在这里推荐 MAXDOP 8?

  • 20

我在 AWS i3.16xlarge 上运行 SQL Server 2022 RC1 设置,具有 2 个套接字、2 个 NUMA 节点、每个节点 32 个逻辑处理器、总共 64 个逻辑处理器。

安装程序推荐 MAXDOP 8:

SQL Server 设置和任务管理器

但是,如果您单击该链接来配置 MAXDOP,建议会说:

MAXDOP 建议

根据那篇知识库文章,MAXDOP 应该是 16,而不是 8。当然,从技术上讲,8 小于 16 - 但 2、4 或 15 也是如此。8 来自哪里?

SQL Server 安装完成并启动服务后,日志显示 SQL Server 正在自动实现具有 4 个节点的 Soft-NUMA,每个节点具有 16 个逻辑处理器:

SQL Server 错误日志

同样,这表明 MAXDOP 应该是 16。

这是一个错误,还是我错过了一些明显的东西?设置将在 MAXDOP 8 停止的地方是否还有其他不成文的规则?

sql-server
  • 2 个回答
  • 1791 Views
Martin Hope
Joe Obbish
Asked: 2022-10-27 09:44:39 +0800 CST

AT TIME ZONE 能否为 2004 年之前的数据返回不准确的结果?

  • 15

SQL Server 2016 添加了AT TIME ZONE运算符。从文档中:

AT TIME ZONE 实现依赖于 Windows 机制来跨时区转换日期时间值。

AT TIME ZONEmscorlib.ni!TimeZoneInfo.ConvertTime根据针对简单查询的 ETW 跟踪调用该方法。Jonathan Kehayias 有一篇博文,他从System.TimeZoneInfo课堂上提取了所有时区规则。我只能在输出中找到 2004 年 1 月 1 日或以后生效的规则:

tz规则

Rob Farley 在一篇博文中提到,2000 年的时区规则更改似乎没有得到遵守AT TIME ZONE:

它通过使用包含所有信息的 Windows 注册表工作,但遗憾的是,当回顾过去时,它并不完美。澳大利亚在 2008 年更改了日期,美国在 2005 年更改了日期——这两个国家在一年中的大部分时间都在节约日光。AT TIME ZONE 明白这一点。但似乎并没有意识到,在 2000 年的澳大利亚,由于悉尼奥运会,澳大利亚在大约两个月前开始实行夏令时。

我觉得有大量间接证据表明,AT TIME ZONE操作员可能会为早于 2004 年的日期返回不准确的结果。但是,我找不到任何AT TIME ZONE使用System.TimeZoneInfo该类的文档,AT TIME ZONE对于较早的日期可能不准确,或者System.TimeZoneInfo该类对于较早的日期可能不准确。

AT TIME ZONE是否存在导致 2004 年之前返回不准确结果的 SQL Server 产品限制?

sql-server
  • 1 个回答
  • 876 Views
Martin Hope
Rebecca
Asked: 2022-10-14 01:44:07 +0800 CST

为什么我在 STRING_AGG 中的 ORDER BY 并不总是有效?

  • 24
这个问题是从 Stack Overflow迁移过来的,因为它可以在 Database Administrators Stack Exchange 上得到回答。 27 天前迁移 。

我有一个表,其中包含一个记录 ID、一个组 ID(将 1 个或多个记录链接到一个组中)和每个记录的哈希值。

CREATE TABLE HashTable(
    RecordID VARCHAR(255),
    GroupIdentifier VARCHAR(255),
    Hash VARCHAR (255),
    GroupHashList VARCHAR(4000)
)

(我知道这不是一个高效的表,但对于本示例而言,它只是一个临时表)。

我想为每个组生成一个哈希,所以我认为最简单的方法是连接组中每个记录的哈希。RecordID 是唯一的,但这些记录相关的内容不一定是唯一的,因此哈希可能是重复的。这样做的目的是标记完全重复的组,即一个组是该组中的所有记录都是另一个组中所有记录的重复。如果要将组的所有成员识别为重复组,则 GUI 需要组的所有成员具有相同的哈希值。

我正在使用 STRING_AGG 连接组中记录的各个散列,并按散列对它们进行排序,以确保我得到重复组的相同字符串。我实际上并不关心哈希的顺序是什么,只要每次都相同。当我将它作为 SELECT 查询运行时,它工作正常,我可以看到重复组的相同字符串。当我采用相同的 SELECT 查询并将其放入 UPDATE 查询时,排序似乎丢失了。

SELECT STRING_AGG([Hash],';') WITHIN GROUP (ORDER BY [Hash] ASC) 
FROM HashTable
GROUP BY [GroupIdentifier]

这给出了结果(例如一对重复组):

73F294873462B2BA0E930FD16DCCB7;90E749375DF806CB6E3F5CA48FFA38;E44256CE7CFCB971EB679BAC25A697
73F294873462B2BA0E930FD16DCCB7;90E749375DF806CB6E3F5CA48FFA38;E44256CE7CFCB971EB679BAC25A697

当我将相同的代码放入 UPDATE 查询时,它没有正确排序它们:

UPDATE HashTable
SET GroupHashList = c.HashList
FROM HashTable
INNER JOIN (
    SELECT (STRING_AGG([Hash],';') WITHIN GROUP (ORDER BY [Hash] ASC)) AS [HashList],
        [GroupIdentifier]
    FROM HashTable
    GROUP BY [GroupIdentifier]) c
ON c.[GroupIdentifier] = HashTable.[GroupIdentifier]

写入表的相同两组的结果:

73F294873462B2BA0E930FD16DCCB7;90E749375DF806CB6E3F5CA48FFA38;E44256CE7CFCB971EB679BAC25A697
73F294873462B2BA0E930FD16DCCB7;E44256CE7CFCB971EB679BAC25A697;90E749375DF806CB6E3F5CA48FFA38

我错过了什么?

我第一次得到的是

Hash1; Hash2; Hash3
Hash1; Hash2; Hash3

但是当它在 UPDATE 查询中时,我得到

Hash1; Hash2; Hash3
Hash1; Hash3; Hash2

更新查询是按记录 ID 排序的,虽然不知道是不是巧合。(https://dbfiddle.uk/CPG1-z2l)

sql-server
  • 1 个回答
  • 1074 Views
Martin Hope
Fajela Tajkiya
Asked: 2022-09-26 08:26:58 +0800 CST

禁用索引的用例是什么?

  • 15

我刚刚了解到可以在表上禁用索引。甚至可以禁用聚集索引。之后,如果聚集索引,用户将无法访问索引或数据。我们什么时候禁用索引?我只是不明白用例。

sql-server index
  • 3 个回答
  • 2256 Views
Martin Hope
Daniel C.
Asked: 2022-06-21 05:34:21 +0800 CST

为什么 MERGE 不会将超过 277 条记录插入配置有时态表和历史表上的非聚集索引的表中

  • 26

我再次发现 SQL Server 和 MERGE 语句存在问题,需要一些确认。

我可以在 Azure 数据库上不断重现我的问题(但不能在本地 SQL Server 2017/2019 上)。

请执行以下步骤(一步一步,而不是一个命令执行)!

1) 架构脚本:

    CREATE TABLE [dbo].[ImpactValueHistory]
    (
        [Rn] BIGINT NOT NULL,

        [ImpactId] UNIQUEIDENTIFIER NOT NULL,
        [ImpactValueTypeId] INT NOT NULL,

        [Date] DATE NOT NULL,
        [Value] DECIMAL(38, 10) NOT NULL,

        [ValidFrom] DATETIME2 NOT NULL CONSTRAINT [DF_ImpactValueHistory_ValidFrom] DEFAULT CONVERT(DATETIME2, '0001-01-01'),
        [ValidTo] DATETIME2 NOT NULL CONSTRAINT [DF_ImpactValueHistory_ValidTo] DEFAULT CONVERT(DATETIME2, '9999-12-31 23:59:59.9999999'),

        [ImpactPeriodId] INT NOT NULL,

        [NormalizedValue] DECIMAL(38, 10) NOT NULL,
    )
    GO

    CREATE CLUSTERED COLUMNSTORE INDEX [COLIX_ImpactValueHistory]
        ON [dbo].[ImpactValueHistory];
    GO

    CREATE NONCLUSTERED INDEX [IX_ImpactValueHistory_ValidFrom_ValidTo_ImpactId_DimensionItemId]
        ON [dbo].[ImpactValueHistory] ([ValidFrom], [ValidTo], [ImpactId], [ImpactValueTypeId], [Date]);
    GO


    CREATE TABLE [dbo].[ImpactValue]
    (
        [Rn] BIGINT NOT NULL IDENTITY(1,1),

        [ImpactId] UNIQUEIDENTIFIER NOT NULL,
        [ImpactValueTypeId] INT NOT NULL,

        [Date] DATE NOT NULL,
        [Value] DECIMAL(38, 10) NOT NULL,

        [ValidFrom] DATETIME2 GENERATED ALWAYS AS ROW START NOT NULL CONSTRAINT [DF_ImpactValue_ValidFrom] DEFAULT CONVERT(DATETIME2, '0001-01-01'),
        [ValidTo] DATETIME2 GENERATED ALWAYS AS ROW END NOT NULL CONSTRAINT [DF_ImpactValue_ValidTo] DEFAULT CONVERT(DATETIME2, '9999-12-31 23:59:59.9999999'),

        [ImpactPeriodId] INT NOT NULL,

        [NormalizedValue] DECIMAL(38, 10) NOT NULL,

        PERIOD FOR SYSTEM_TIME ([ValidFrom], [ValidTo]),

        CONSTRAINT [PK_ImpactValue] PRIMARY KEY NONCLUSTERED ([ImpactId], [ImpactValueTypeId], [Date], [ImpactPeriodId])
    )
    WITH (SYSTEM_VERSIONING = ON (HISTORY_TABLE = [dbo].[ImpactValueHistory]))
    GO

    CREATE UNIQUE CLUSTERED INDEX [IX_ImpactValue_Id] ON [dbo].[ImpactValue]([Rn])
    GO

    CREATE COLUMNSTORE INDEX [CIX_ImpactValue] ON [dbo].[ImpactValue] ([ImpactId], [ImpactValueTypeId], [Date], [Value], [NormalizedValue])
    GO

2) 插入一些随机数据的脚本

DECLARE @inserted0 TABLE ([Date] DATE, [ImpactId] uniqueidentifier, [ImpactPeriodId] int, [ImpactValueTypeId] int);
MERGE [dbo].[ImpactValue] USING (
SELECT TOP 278 -- <-- this number is critical
        DATEADD(MONTH, ROW_NUMBER() OVER(ORDER BY [Name]) - 1, '2000-01-01') AS [Date],
        NEWID() AS [ImpactId], 
        1 AS [ImpactPeriodId], 
        1 AS [ImpactValueTypeId], 
        99 AS [Value], 
        99 AS [NormalizedValue]
    FROM [sys].[all_columns]
) AS i ([Date], [ImpactId], [ImpactPeriodId], [ImpactValueTypeId], [Value], [NormalizedValue]) ON 1=0
WHEN NOT MATCHED THEN
INSERT ([Date], [ImpactId], [ImpactPeriodId], [ImpactValueTypeId], [Value], [NormalizedValue])
VALUES (i.[Date], i.[ImpactId], i.[ImpactPeriodId], i.[ImpactValueTypeId], i.[Value], i.[NormalizedValue])
OUTPUT INSERTED.[Date], INSERTED.[ImpactId], INSERTED.[ImpactPeriodId], INSERTED.[ImpactValueTypeId]
INTO @inserted0;

SELECT * FROM @inserted0

这一步应该返回所有插入的行!

3)从步骤2中删除数据) 这一步正在填充配置的历史表

DELETE [dbo].[ImpactValue]

4)再次插入一些随机数据 您可以使用步骤2中的脚本)

我必须注意,步骤 1) - 4) 应该单独执行,而不是在GO.

这一步应该再次返回所有插入的行!但事实并非如此! 在我这边,我总是得到一个空的结果。这可以在我们的三个生产数据库上重现:(

MERGE 语句由 EF Core 生成,目前我正在通过设置 Max Batch Size 来解决此问题。但这不可能是最终的解决方案。

它必须与在时态表上配置了非聚集索引的时态表有关。

也可以看看:

在过去,我已经偶然发现了这个问题:

  • https://stackoverflow.com/questions/70734060/why-does-a-merge-into-a-temporal-table-with-a-nonclustered-index-in-the-history。
  • https://github.com/dotnet/efcore/issues/22852

但是我当前的问题只能在 Azure SQL 数据库上重现,并且不会引发任何错误。

有趣的旁注:

  1. 如果我暂时禁用临时表->它正在工作
  2. 如果我删除非聚集索引 [IX_ImpactValueHistory_ValidFrom_ValidTo_ImpactId_DimensionItemId] -> 它正在工作
  3. 如果我在步骤 2 中使用 SELECT TOP (@BatchSize) -> 它正在工作
  4. 如果我只使用 OUTPUT 而不是 OUTPUT INTO @inserted0 --> 它正在工作

如果没有历史表上的 COLUMNSTORE 索引,它就可以工作。通过仅删除主表上的 COLUMNSTORE 索引,我看到了同样的问题。

TOP 278(a) 重现问题和 (b) 不重现的情况的实际执行计划TOP (@BatchSize)可在https://1drv.ms/u/s!AsOa6e9ukBWQlIRg9_9eySDFp5hvEA?e=KBQBsP获得。我还添加了批量大小为 277 的实际执行计划。两者都使用这个大小!

azure-sql-database merge
  • 1 个回答
  • 2016 Views
Martin Hope
icecurtain
Asked: 2022-05-12 12:50:20 +0800 CST

勒索软件可以将自己嵌入到 SQL 备份文件中吗?

  • 15

针对勒索软件的最佳保护之一是将所有数据库文件备份到一个完全独立的系统。我们已经做到了。

但一种想法是数据库的备份现在可能包含勒索软件。这可能吗?这是 2016 SQL Server 本机创建的 .bak。还是勒索软件不可能将自己嵌入到备份文件中?

sql-server sql-server-2016
  • 5 个回答
  • 3378 Views
Martin Hope
Quasimodo's clone
Asked: 2022-03-15 07:23:47 +0800 CST

表和视图有通用术语吗?

  • 19

我正在寻找一个通用术语,例如数据库抽象,它包括所有表格数据结构,如数据库表、视图、表格查询结果等。

据我了解,“实体”不是正确的术语,因为它对应于表而不是视图甚至查询。“结果”在可修改的数据结构上是违反直觉的。

在专业环境中,哪个是合适的术语?

query view
  • 6 个回答
  • 2530 Views
Martin Hope
User M
Asked: 2021-08-23 23:51:57 +0800 CST

当 ID (INT) 上存在聚集索引时,根据日期对表(在 MS SQL 中)进行分区是个好主意吗

  • 16

我在 MS SQL Server 中有一张表。

  • 表大小:806 GB
  • 行数:12 亿
  • 索引空间:1.2 GB

表用法:来自 Web 服务调用的日志记录 99.9% 是来自日志记录的用法,开发人员很少在 Prod 中查看此表(仅在报告或研究问题时)。

主键:基于“INT”数据类型的“ID”。有一个基于该“ID”列的聚集索引。

我对此更改的意图:想要管理此表(因为它有 10 年的数据)并继续前进(由于新要求),开发人员/分析师有可能进一步深入研究此表(仅几个月)而且我不想为相同的目的创建一个新表。

我的问题:

  1. [主要问题]我可以根据“DateCreated”(DATETIME,NOT NULL 列)对该表进行分区,而不会导致问题(逻辑/性能方面)。

  2. [很高兴知道]需要多少时间(我知道这取决于数据库空间/服务器内存和其他详细信息,但大致 # 会很好)对这个巨大的表进行分区(如果可以根据日期进行分区) . 问这个问题,因为这是一个生产表,并且经常插入行(现在 ~ 350 条记录/分钟)。

  3. 【不完全是个问题,求推荐】有没有更好的方案来管理这张表(不想在Production中保留超过3年的数据,方案在下面提到)?

当前计划(我是 MS SQL 的新手,所以这是我想出的):

  • 每个分区保留 3 个月的数据。
  • 系统在每个季度之前自动创建分区。
  • 在活动表中只保留 3 年的分区。
  • 将其他分区移动到 OLD/ARCHIEVE 表(需要创建这个)。真正要清除的旧数据。
sql-server partitioning
  • 4 个回答
  • 3304 Views
Martin Hope
Mate Michelisz
Asked: 2021-06-22 00:15:35 +0800 CST

为什么数据库的默认页面大小如此之小?

  • 29

在 PostgreSQL 和 SQL Server 中,默认页面大小为 8 KB,在 MySQL 中为 16 KB,在 IBM DB2 和 Oracle 中仅为 4 KB。

为什么这些页面尺寸这么小?

是否有历史或内存使用原因?

sql-server mysql
  • 3 个回答
  • 5399 Views
Martin Hope
SQLing4ever
Asked: 2021-05-28 10:27:16 +0800 CST

SQL Server 内存优化 tempdb 元数据内存使用量持续增长

  • 19

问题

我们启用了 sp_configure 'tempdb metadata memory-optimized' = 1,现在 tempdb 元数据在我们的一台服务器上占用了 400 GB 以上,并且还在继续增长。内存使用量有所下降,但通常它会不断增长它的内存使用量。我们已经有几次服务器实际上崩溃了,因为没有足够的内存供其他系统进程修改 tempdb 并导致整个服务器停机。

我要问的问题

如何防止 SQL Server 内存中优化的 tempdb 元数据持续增长并使我的服务器崩溃?如果有的话,我可以查看哪些其他信息来找出消耗这么多内存的原因?

有关问题的数据

sys.dm_os_memory_clerks

以下查询当前返回 438 GB。

SELECT SUM(domc.pages_kb / 1024.0 / 1024.0) AS pages_gb
FROM sys.dm_os_memory_clerks AS domc
WHERE domc.type LIKE 'MEMORYCLERK_XTP'

sys.dm_db_xtp_memory_consumers

以下查询提供了内存使用量最大 (290 GB) 为 memory_consumer_id of 113 - 'LOB Page Allocator' 的数据。它没有object_id 或xtp_object_id,所以我猜它是一个数据库范围的对象。

SELECT ddxmc.memory_consumer_id
     , ddxmc.memory_consumer_type_desc
     , ddxmc.memory_consumer_desc
     , ddxmc.object_id
     , ddxmc.xtp_object_id
     , ddxmc.used_bytes / 1024.0 / 1024.0 / 1024.0 AS used_gb
FROM sys.dm_db_xtp_memory_consumers AS ddxmc
ORDER BY ddxmc.allocated_bytes DESC

环境

版本:SQL Server 2019 CU9 -
机箱上的企业内存:3 TB
实例类型:故障转移集群实例
操作系统:Windows Server 2019 标准
CPU 核心数:80 个物理核心(我们最近不得不增加这个数字) Tempdb 的数量文件:64 复制:此服务器是事务复制的发布者和订阅者。

使用模式

我们是 tempdb 的重度用户。我们一直在存储过程中不断地创建和删除临时表和表变量。我们需要处理大量数据,传入数据列表,然后将这些数据列表转换为表格来处理结果集数据,而不是一次处理一条信息。由于 tempdb 的大量流失,我们不得不实现内存中优化的 tempdb 以减轻我们遇到的 PAGELATCH_* 等待。

我很确定没有任何内存优化的用户表。当我运行以下查询时,我只看到SYSTEM_TABLE类型对象:

SELECT *
FROM sys.dm_db_xtp_index_stats AS ddxis
    JOIN sys.objects AS o ON o.object_id = ddxis.object_id

我知道的事情和我尝试过的事情

内存垃圾收集只能清理比最旧事务更早的项目。

我很清楚垃圾收集只能发生在比最旧事务更早的行上,因此我已经停止了所有长时间运行的 SQL 代理作业和任何其他超过 5 分钟的进程。不幸的是,我们的内存使用量并没有回落。我们确实有旧会话,但根据以下查询,它们都没有打开任何事务。

SELECT *
FROM sys.dm_exec_sessions AS des
WHERE des.open_transaction_count > 0

复制

为了排除复制,我确实暂时停止了此服务器的发布和订阅代理。内存使用没有变化。

检查点

我在 tempdb 中运行了“CHECKPOINT”。内存使用量没有下降。

DBCC FREEPROCCACHE - 摆脱旧的临时表

为了删除正在缓存的旧临时表,我清除了查询计划缓存,并通过运行以下查询验证了临时表是否已重新创建。这并没有导致内存使用量大幅下降。

SELECT *
FROM sys.tables AS t
WHERE t.name LIKE '#%'
    AND t.create_date < 'TimeOfClearingPlanCache'

其他可能的解决方案

重新启动 SQL Server

我们可以重新启动 SQL Server,它确实可以缓解一段时间的问题,但一段时间后内存使用量确实会再次增加。虽然这是一种解决方法,但这是一个我们不太喜欢的糟糕解决方案。

关闭“内存中优化的 Tempdb”

我们可以关闭“内存中优化的 tempdb”,但是我们会受到我们之前经历过的大量 PAGELATCH_* 等待的影响。我们有 64 个 tempdb 文件来帮助减少我们看到的争用,但在我们繁忙的时期,即使这样也不够。这可能是一种选择,但最好是我们能找到内存使用量持续增长的原因。

sql-server memory
  • 2 个回答
  • 2376 Views
Martin Hope
ERJAN
Asked: 2021-03-21 00:47:49 +0800 CST

如果 NoSQL 代表“Not only SQL”,那么 SQL 是 NoSQL 的子集吗?

  • 25

这个定义有点令人困惑——基本上我是在问 SQL 是否是 NoSQl 系列的一个子集:

kk

我问这个是因为“不仅”意味着 NoSQL 更大,但仍将 SQL 作为其中的一部分。

另一方面,由于我们不能在 NoSQL 数据库中执行典型的 sql 操作,例如连接,所以 SQL 不是 nosql 的一部分!

我想知道哪个是真的?

rdbms nosql
  • 4 个回答
  • 6154 Views
Martin Hope
Danilo Matrangolo Marano
Asked: 2021-01-12 14:44:35 +0800 CST

SQL Server 中的 GO 语句有什么作用?

  • 50

SQL Server的GO语句引起了我极大的好奇心,我真的不知道如何正确使用它。

我注意到无论有没有查询GO都不会返回错误并且似乎工作相同,那么它的目的是什么,我为什么要使用它?

;分号和GO查询末尾有什么区别?

sql-server
  • 5 个回答
  • 10540 Views
Martin Hope
jwize
Asked: 2020-10-16 12:12:50 +0800 CST

同事说永远不要在 SQL 中使用 OR 语句,这是真的吗?

  • 17

我现在负责 SQL 开发的同事说我永远不应该使用OR语句,因为它会弄乱查询优化器并忽略产生缓慢查询的表索引。我在谷歌搜索时找不到任何这样的例子。以下查询的替代方案变得非常难看,有十几个代码块,这些代码块看起来几乎相同(与示例相同),对每个变量状态使用 if else 语句。注意检查短路的变量,如果值为 2,则返回所有结果,否则按字段过滤。

我询问了一些包含这些关于为什么不使用OR语句的声明的资源,并收到了以下链接(我们使用的是 MS SQL Server)。

  • https://stackoverflow.com/questions/5639710/union-all-vs-or-condition-in-sql-server-query
  • https://bertwagner.com/2018/02/20/or-vs-union-all-is-one-better-for-performance/
  • http://sqlserverplanet.com/optimization/using-union-instead-of-or

这些示例似乎都不像下面的当前实现。我很难相信这段代码有问题,但如果有问题请告诉我。我还想了解更多关于不使用的评论OR实际上可能成立的信息以及为什么如此,以便更好地理解这个问题。

SELECT
    e.EmployeeName,
    e.DepartmentName,
    crs.Title,
    c.Name as CompanyName
FROM Employee E
Left Outer Join Company c ON c.Id = @companyId
    INNER JOIN Department d on e.DepartmentId = d.Id 
WHERE   
    c.Id = @companyId           
    AND (@Active = 2 OR  crs.IsActive = @Active)
    AND (@Dot = 2 OR IsDot = @Dot)
    AND crs.CompanyId = @companyId
    AND d.CompanyId = @companyId
ORDER BY EmployeeName, Title, PassedDate

我相信除非有充分的理由,否则复制代码总是不好的。测试查询后,我确认使用了正确的索引。提到这一点后,我被告知他会使用最佳实践。我还没有看到任何最佳实践告诉我不要使用OR. 谁能带我去这些?


这是我很久以前更新之前的可憎之处。如果您发现@Department并对此感到疑惑,那不是错误。Telerik 报告组件正在对这段代码做一些事情,并在后台扩展一个数组,然后再到达服务器。

IF @Active = 2
BEGIN
--ACTIVE AND INACTIVE
    IF 0 IN (@Department)
    BEGIN
        IF @DOT = 1 
        BEGIN
            Select 
            A.LastName + ', ' + A.FirstName as EmployeeName,
            A.DepartmentName,
            C.Title,
            ISNULL(B.Comments, ' ') as Remarks,
            CONVERT(varchar, B.PassedDate, 101) as DateOut,
            D.Name as CompanyName

            FROM Employee A
            Left Outer Join EmployeeCourse B    ON A.Id = B.EmployeeId
            Left Outer Join CompanyCourse C     ON B.CompanyCourseId = C.Id
            Left Outer Join Company D           ON @companyId = D.Id

            WHERE   A.CompanyId = @companyId 
                    AND B.PassedDate IS Not NULL 
                    AND C.DotCourse = 1 

            ORDER BY EmployeeName, Title, PassedDate
        END

        IF @DOT = 0 
        BEGIN
            Select 
            A.LastName + ', ' + A.FirstName as EmployeeName,
            A.DepartmentName,           
            C.Title,
            ISNULL(B.Comments, ' ') as Remarks,
            CONVERT(varchar, B.PassedDate, 101) as DateOut,
            D.Name as CompanyName

            FROM Employee A
            Left Outer Join EmployeeCourse B    ON A.Id = B.EmployeeId
            Left Outer Join CompanyCourse C     ON B.CompanyCourseId = C.Id
            Left Outer Join Company D           ON @companyId = D.Id

            WHERE   A.CompanyId = @companyId 
                    AND B.PassedDate IS Not NULL 
                    
            ORDER BY EmployeeName, Title, PassedDate
        END

        IF @DOT = 2 
            BEGIN
            Select 
            A.LastName + ', ' + A.FirstName as EmployeeName,
            A.DepartmentName,           
            C.Title,
            ISNULL(B.Comments, ' ') as Remarks,
            CONVERT(varchar, B.PassedDate, 101) as DateOut,
            D.Name as CompanyName

            FROM Employee A
            Left Outer Join EmployeeCourse B    ON A.Id = B.EmployeeId
            Left Outer Join CompanyCourse C     ON B.CompanyCourseId = C.Id
            Left Outer Join Company D       ON @companyId = D.Id

            WHERE   A.CompanyId = @companyId 
                    AND B.PassedDate IS Not NULL 
                    AND C.DotCourse = 0 
                    
            ORDER BY EmployeeName, Title, PassedDate
        END 
    END
    ELSE
    BEGIN
        IF @DOT = 1 
        BEGIN
            Select 
            A.LastName + ', ' + A.FirstName as EmployeeName,
            A.DepartmentName,
            C.Title,
            ISNULL(B.Comments, ' ') as Remarks,
            CONVERT(varchar, B.PassedDate, 101) as DateOut,
            D.Name as CompanyName

            FROM Employee A
            Left Outer Join EmployeeCourse B    ON A.Id = B.EmployeeId
            Left Outer Join CompanyCourse C     ON B.CompanyCourseId = C.Id
            Left Outer Join Company D           ON @companyId = D.Id

            WHERE   A.CompanyId = @companyId 
                    AND B.PassedDate IS Not NULL 
                    AND C.DotCourse = 1
                    AND A.DepartmentId IN (@Department)

            ORDER BY EmployeeName, Title, PassedDate
        END

        IF @DOT = 0 
        BEGIN
            Select 
            A.LastName + ', ' + A.FirstName as EmployeeName,
            A.DepartmentName,
            C.Title,
            ISNULL(B.Comments, ' ') as Remarks,
            CONVERT(varchar, B.PassedDate, 101) as DateOut,
            D.Name as CompanyName

            FROM Employee A
            Left Outer Join EmployeeCourse B    ON A.Id = B.EmployeeId
            Left Outer Join CompanyCourse C     ON B.CompanyCourseId = C.Id
            Left Outer Join Company D           ON @companyId = D.Id

            WHERE   A.CompanyId = @companyId 
                    AND B.PassedDate IS Not NULL 
                    AND A.DepartmentId IN (@Department)
                    
            ORDER BY EmployeeName, Title, PassedDate
        END

        IF @DOT = 2 
        BEGIN
            Select 
            A.LastName + ', ' + A.FirstName as EmployeeName,
            A.DepartmentName,
            C.Title,
            ISNULL(B.Comments, ' ') as Remarks,
            CONVERT(varchar, B.PassedDate, 101) as DateOut,
            D.Name as CompanyName

            FROM Employee A
            Left Outer Join EmployeeCourse B    ON A.Id = B.EmployeeId
            Left Outer Join CompanyCourse C     ON B.CompanyCourseId = C.Id
            Left Outer Join Company D           ON @companyId = D.Id

            WHERE   A.CompanyId = @companyId 
                    AND B.PassedDate IS Not NULL 
                    AND C.DotCourse = 0 
                    AND A.DepartmentId IN (@Department)
                    
            ORDER BY EmployeeName, Title, PassedDate
        END 
    END
END
ELSE
BEGIN
--ACTIVE OR INACTIVE
    IF 0 IN (@Department)
    BEGIN
        IF @DOT = 1 
        BEGIN
            Select 
            A.LastName + ', ' + A.FirstName as EmployeeName,
            A.DepartmentName,
            C.Title,
            ISNULL(B.Comments, ' ') as Remarks,
            CONVERT(varchar, B.PassedDate, 101) as DateOut,
            D.Name as CompanyName

            FROM Employee A
            Left Outer Join EmployeeCourse B    ON A.Id = B.EmployeeId
            Left Outer Join CompanyCourse C     ON B.CompanyCourseId = C.Id
            Left Outer Join Company D           ON @companyId = D.Id

            WHERE  A.IsActive = @Active 
                    AND A.CompanyId = @companyId 
                    AND B.PassedDate IS Not NULL 
                    AND C.DotCourse = 1 

            ORDER BY EmployeeName, Title, PassedDate
        END

        IF @DOT = 0 
        BEGIN
            Select 
            A.LastName + ', ' + A.FirstName as EmployeeName,
            A.DepartmentName,
            C.Title,
            ISNULL(B.Comments, ' ') as Remarks,
            CONVERT(varchar, B.PassedDate, 101) as DateOut,
            D.Name as CompanyName

            FROM Employee A
            Left Outer Join EmployeeCourse B    ON A.Id = B.EmployeeId
            Left Outer Join CompanyCourse C     ON B.CompanyCourseId = C.Id
            Left Outer Join Company D           ON @companyId = D.Id

            WHERE  A.IsActive = @Active 
                    AND A.CompanyId = @companyId 
                    AND B.PassedDate IS Not NULL 
                    
            ORDER BY EmployeeName, Title, PassedDate
        END

        IF @DOT = 2 
            BEGIN
            Select 
            A.LastName + ', ' + A.FirstName as EmployeeName,
            A.DepartmentName,
            C.Title,
            ISNULL(B.Comments, ' ') as Remarks,
            CONVERT(varchar, B.PassedDate, 101) as DateOut,
            D.Name as CompanyName

            FROM Employee A
            Left Outer Join EmployeeCourse B    ON A.Id = B.EmployeeId
            Left Outer Join CompanyCourse C     ON B.CompanyCourseId = C.Id
            Left Outer Join Company D       ON @companyId = D.Id

            WHERE  A.IsActive = @Active 
                    AND A.CompanyId = @companyId 
                    AND B.PassedDate IS Not NULL 
                    AND C.DotCourse = 0 
                    
            ORDER BY EmployeeName, Title, PassedDate
        END 
    END
    ELSE
    BEGIN
        IF @DOT = 1 
        BEGIN
            Select 
            A.LastName + ', ' + A.FirstName as EmployeeName,
            A.DepartmentName,
            C.Title,
            ISNULL(B.Comments, ' ') as Remarks,
            CONVERT(varchar, B.PassedDate, 101) as DateOut,
            D.Name as CompanyName

            FROM Employee A
            Left Outer Join EmployeeCourse B    ON A.Id = B.EmployeeId
            Left Outer Join CompanyCourse C     ON B.CompanyCourseId = C.Id
            Left Outer Join Company D           ON @companyId = D.Id

            WHERE  A.IsActive = @Active
                    AND A.CompanyId = @companyId 
                    AND B.PassedDate IS Not NULL 
                    AND C.DotCourse = 1
                    AND A.DepartmentId IN (@Department)

            ORDER BY EmployeeName, Title, PassedDate
        END

        IF @DOT = 0 
        BEGIN
            Select 
            A.LastName + ', ' + A.FirstName as EmployeeName,
            A.DepartmentName,
            C.Title,
            ISNULL(B.Comments, ' ') as Remarks,
            CONVERT(varchar, B.PassedDate, 101) as DateOut,
            D.Name as CompanyName

            FROM Employee A
            Left Outer Join EmployeeCourse B    ON A.Id = B.EmployeeId
            Left Outer Join CompanyCourse C     ON B.CompanyCourseId = C.Id
            Left Outer Join Company D           ON @companyId = D.Id

            WHERE  A.IsActive = @Active 
                    AND A.CompanyId = @companyId 
                    AND B.PassedDate IS Not NULL 
                    AND A.DepartmentId IN (@Department)
                    
            ORDER BY EmployeeName, Title, PassedDate
        END

        IF @DOT = 2 
        BEGIN
            Select 
            A.LastName + ', ' + A.FirstName as EmployeeName,
            A.DepartmentName,
            C.Title,
            ISNULL(B.Comments, ' ') as Remarks,
            CONVERT(varchar, B.PassedDate, 101) as DateOut,
            D.Name as CompanyName

            FROM Employee A
            Left Outer Join EmployeeCourse B    ON A.Id = B.EmployeeId
            Left Outer Join CompanyCourse C     ON B.CompanyCourseId = C.Id
            Left Outer Join Company D           ON @companyId = D.Id

            WHERE  A.IsActive = @Active 
                    AND A.CompanyId = @companyId 
                    AND B.PassedDate IS Not NULL 
                    AND C.DotCourse = 0 
                    AND A.DepartmentId IN (@Department)
                    
            ORDER BY EmployeeName, Title, PassedDate
        END 
    END
END

注意:我在初始代码示例中删除了一些以简化。

根据他的解释、链接和我的搜索,我很难相信我当前的解决方案在性能和可读性方面不是最好的。我接受可能存在一些可能会降低性能的情况,但我高度怀疑我的实施是否属于这种情况。OR当我没有看到任何说明这一点的文档时,我不喜欢永远不应该使用的想法。

当我显示查询时,我被告知作为概括永远不要使用OR. 我现在正在做功课,看看这是否是有效的信息。我真的很讨厌使用以前的代码,因为错误的方式太多了。

sql-server query-performance
  • 3 个回答
  • 3516 Views
Martin Hope
yegnasew
Asked: 2020-07-10 05:36:58 +0800 CST

截断 AG 中包含 170 亿行的表

  • 20

我需要截断一个包含 170 亿行的表,该表位于作为 AG 一部分的数据库中。

此操作对 AG 延迟和日志备份大小有何影响?

有推荐的方法吗?

sql-server availability-groups
  • 2 个回答
  • 3761 Views
Martin Hope
Brent Ozar
Asked: 2020-07-07 06:31:59 +0800 CST

如何拒绝写入所有 SQL Server 数据库(包括新的和恢复的)

  • 15

我想创建一个被拒绝写入任何数据库的登录名 - 不仅仅是今天存在的数据库,还有任何新创建的数据库或从其他服务器恢复的数据库。

我不能使用仅数据库角色(甚至在模型中),因为这些角色不会对新恢复的数据库生效。

(商业目的:我正在写一篇关于人们如何为自己设置低权限的新登录的博客文章,并且他们可以确保他们在复制/粘贴代码时不会意外地出现“糟糕”的时刻或在没有 where 子句的情况下运行它。)

sql-server security
  • 7 个回答
  • 1922 Views
Martin Hope
Heinzi
Asked: 2020-04-28 02:28:48 +0800 CST

SQL Server 2019 执行无法访问的代码

  • 34

[更新:此问题描述了已在SQL Server 2019 的累积更新 5 中修复的错误。]


考虑以下复制示例(小提琴):

CREATE FUNCTION dbo.Repro (@myYear int)
RETURNS datetime
AS
BEGIN
    IF @myYear <> 1990
    BEGIN
        RETURN NULL
    END

    DECLARE @firstOfYear datetime;
    SET @firstOfYear = DATEFROMPARTS(@myYear, 1, 1);
    
    IF DATEDIFF(day, @firstOfYear, @firstOfYear) <> 0
    BEGIN
        RETURN NULL
    END

    RETURN @firstOfYear
END
SELECT dbo.Repro(0);

显然,如果输入为1990,则该函数应返回 1990 年 1 月的第一天,NULL否则返回。是的,我知道这DATEDIFF(day, @firstOfYear, @firstOfYear) <> 0是一个荒谬的操作。这是一个演示潜在错误的mcve ,而不是生产代码。

现在让我们SELECT dbo.Repro(0)在 SQL Server 2017 和 SQL Server 2019 上执行。

预期结果:NULL。

SQL Server 2017 上的实际结果:NULL

SQL Server 2019 上的实际结果:

消息 289 级别 16 状态 1 行 1
无法构造数据类型日期,某些参数的值无效。

显然,SQL Server 2019 会执行初始保护子句 ( IF @myYear <> 1990) 下面的一些代码,即使它不应该执行。

我的问题:

  • 这是预期的行为,还是我在 SQL Server 2019 中发现了错误?
  • 如果这是预期的行为,我该如何正确编写验证输入参数的保护子句?
sql-server functions
  • 1 个回答
  • 2394 Views

Sidebar

Stats

  • 问题 199037
  • 回答 263511
  • 最佳答案 131755
  • 用户 66345
  • 热门
  • 回答
  • 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