标签: sql-server

NCCI 中的 Lob 逻辑读取和 lob 预读

我有一个具有以下结构的测试表。

CREATE TABLE [dbo].[DW_test](
[ID] [bigint] IDENTITY(1,1) NOT NULL,
[CourtCaseID] [int] NOT NULL,
[ActionID] [int] NOT NULL,
PRIMARY KEY CLUSTERED([ID] ASC)
Run Code Online (Sandbox Code Playgroud)

接下来,我使用以下脚本在我的表中填充了大约 4.7 亿条记录。

insert into DW_test
--select count(*)
--from (
select top 1000000 abs(checksum(newid())) % 100000 + 1 a, abs(checksum(newid())) % 10 + 1 b
from sys.all_objects
cross join sys.all_objects a
cross join sys.all_objects b
cross join sys.all_objects c
cross join sys.all_objects d
cross join sys.all_objects e
cross join sys.all_objects f
cross join sys.all_objects g
--) t
GO
Run Code Online (Sandbox Code Playgroud)

该脚本执行了大约 …

sql-server columnstore sql-server-2017

8
推荐指数
2
解决办法
524
查看次数

使用隐式类型转换插入会导致基数估计警告

我最近在做一些性能测试时注意到了这一点。当我将一个值插入到需要隐式转换(例如bigintinto nvarchar)的列中时,我收到一条警告:

表达式中的类型转换(CONVERT_IMPLICIT(nvarchar(50),[tempdb].[dbo].[#MyFunIntTable].[EvenCoolerColumn],0))可能会影响查询计划选择中的“基数估计”。

作为一个关心的公民,我检查了所有明显的嫌疑人,并最终深入研究了 XML 以确认它实际上是关于插入表的警告。问题是,我无法弄清楚为什么这会影响基数估计。如果我在连接中或在具有更多逻辑的地方执行此操作,那将是有道理的,但是实际插入操作不应该存在基数估计不匹配,对吗?

我注意到当它不仅仅是一个简单的查询时会发生这种情况 - 只要插入了多个值,或者我们从表中提取一个值,我们就会点击这个。

这个问题吸引了一些潜在的重复,包括:

我认为它与这些问题不同,因为我实际上没有对这个专栏做任何事情。我没有在过滤器、排序、分组、连接或函数中使用它 - 这些东西中的任何一个都会使场景变得更加复杂。我所做的只是将 a 插入bigint到 a 中nvarchar,这永远不会影响我能想到的有意义的基数估计。

我特别想从答案中寻找的是:

  1. 解释为什么我在没有任何兴趣的情况下收到此警告 - 是否只是 SQL Server 会保守并报告,即使它不会影响计划选择?
  2. 什么基数估计在这里实际上存在风险,基于该基数估计的不准确性,哪些操作会发生变化?
  3. 是否存在这会影响计划选择的情况?显然,如果我开始加入或过滤转换后的列,它可以,但按原样?
  4. 除了更改数据类型(假设这是数据模型交互方式的要求)之外,还有什么可以防止它发出警告的吗?

我用下面的简单例子重新创建了它(粘贴计划

DROP TABLE IF EXISTS #MyFunStringTable;
DROP TABLE IF EXISTS #MyFunIntTable;

CREATE TABLE #MyFunStringTable
(
  SuperCoolColumn nvarchar(50) COLLATE DATABASE_DEFAULT NULL
);

CREATE TABLE #MyFunIntTable
(
  EvenCoolerColumn bigint NULL
);

INSERT INTO #MyFunIntTable
( EvenCoolerColumn …
Run Code Online (Sandbox Code Playgroud)

sql-server t-sql execution-plan cardinality-estimates

8
推荐指数
1
解决办法
458
查看次数

使用的数据库镜像协议 TCP 端口。一种默认,一种动态?

在 SQL Server Always On Availability Group™ 的主要/次要副本上运行以下查询时

SELECT DISTINCT local_tcp_port,protocol_type,num_reads,num_writes
FROM sys.dm_exec_connections 
WHERE local_net_address is not null;
Run Code Online (Sandbox Code Playgroud)

为数据库镜像协议显示了两个本地 tcp 端口,5022&63420

Server Name local_tcp_port  protocol_type       num_reads   num_writes
ServerName  5022            Database Mirroring  102942598   5
ServerName  63420           Database Mirroring  5           89655349
Run Code Online (Sandbox Code Playgroud)

5022端口是预期的,因为这是配置为镜像端点的端口。

另一个似乎是一个动态端口,为什么使用这个端口以及用于什么?

是否与一个显示大量读取 ( 5022) 和另一个显示大量写入 ( 63420)的事实有关。

构建版本:13.0.5264.1

sql-server availability-groups sql-server-2016

8
推荐指数
1
解决办法
2193
查看次数

在 where 子句中同时使用“包含”和“=”时查询速度很慢

以下查询需要大约 10 秒才能在具有 12k 条记录的表上完成

select top (5) *
from "Physician"
where "id" = 1 or contains("lastName", '"a*"')
Run Code Online (Sandbox Code Playgroud)

但是,如果我将 where 子句更改为

where "id" = 1
Run Code Online (Sandbox Code Playgroud)

或者

where contains("lastName", '"a*"')
Run Code Online (Sandbox Code Playgroud)

它会立即返回。

两列都被索引,lastName 列也被全文索引。

CREATE TABLE Physician
(
   id         int identity    NOT NULL,
   firstName  nvarchar(100)   NOT NULL,
   lastName   nvarchar(100)   NOT NULL
);

ALTER TABLE Physician
  ADD CONSTRAINT Physician_PK
  PRIMARY KEY CLUSTERED (id);

CREATE NONCLUSTERED INDEX Physician_IX2
   ON Physician (firstName ASC);

CREATE NONCLUSTERED INDEX Physician_IX3
   ON Physician (lastName ASC);

CREATE FULLTEXT INDEX
    ON …
Run Code Online (Sandbox Code Playgroud)

sql-server full-text-search sql-server-2008-r2

8
推荐指数
1
解决办法
562
查看次数

究竟是什么触发了 sys.database_files 列 is_media_read_only 的 UPDATE?

愿意解决这个问题涉及到一个错误的值is_media_read_only数据库属性我做了一些研究和试验,但最终我不能梳理一下究竟触发列的更新is_media_read_onlysys.database_files

根据sys.database_files文档,该列is_media_read_only应具有以下两个可能值之一:

1 = 文件位于只读媒体上。

0 = 文件在读写介质上。

有了这些信息,我对两个不同版本的 SQL Server 进行了以下实验:

Microsoft SQL Server 2014 (SP3-GDR) (KB4505218) - 12.0.6108.1 (X64)
Microsoft SQL Server 2017 (RTM-CU16) (KB4508218) - 14.0.3223.3 (X64)

在我的笔记本(驱动器 E:) 中插入一个笔式驱动器并创建一个数据库,如下所示:

CREATE DATABASE [MyDB]
 ON  PRIMARY 
( NAME = N'MyDB_01', FILENAME = N'D:\DataBases\MyDB_01.mdf'), 
 FILEGROUP [SECONDARY] 
( NAME = N'MyDB_02', FILENAME = N'E:\DataBasesPendrive\MyDB_02.ndf')
 LOG ON 
( NAME = N'MyDB_log', FILENAME = N'D:\DataBases\MyDB_log.ldf')
GO
Run Code Online (Sandbox Code Playgroud)

查询 sys.database_files: …

sql-server system-tables

8
推荐指数
2
解决办法
324
查看次数

SQL Server 中用于保留用于批量插入的 id 块的惯用解决方案是什么?

我有一个带有标识列的表,我想保留一个可用于批量插入的 id 块,同时允许插入仍然发生在该表中。

请注意,这是多个表的批量插入的一部分,其中其他表通过 FK 与这些 id 相关。因此,我需要将它们挡在外面,以便我可以事先准备好关系。

我找到了一个解决方案,它通过在事务中锁定表然后进行重新播种(非常快)来工作。但这对我来说看起来有点老套 - 这样做是否有普遍接受的模式?

create table dbo.test
(
    id bigint not null primary key identity(1,1),
    SomeColumn nvarchar(100) not null
)
Run Code Online (Sandbox Code Playgroud)

这是阻止(为)一些 id 的代码:

declare @numRowsToMakeRoomFor int = 100

BEGIN TRANSACTION;

        SELECT  MAX(Id) FROM dbo.test WITH (  XLOCK, TABLOCK ) -- will exclusively lock the table whilst this tran is in progress, 
        --another instance of this query will not be able to pass this line until this instance commits

        --get the next id in …
Run Code Online (Sandbox Code Playgroud)

sql-server identity sql-server-2016 bulk-insert

8
推荐指数
1
解决办法
1088
查看次数

确定是否正在进行自动统计更新

在我们的生产系统中,查询有时会“停滞”。在停止时,sp_whoisactive 中没有显示增加的资源使用(CPU、读取),并且没有阻塞。

在回顾性诊断中,我们可以看到 sys.dm_db_stats_properties 显示 last_updated 大约在查询“停滞”时。

我们想要做的是——当我们看到一个停滞的查询时——然后确定正在进行哪些自动统计更新。

因为我们想要临时执行此操作,也因为我们不想影响生产性能,所以使用分析器可能不是我们的选择。

(如果没有办法进行临时决定,那么也许我们将不得不考虑扩展事件或其他一些影响较小的先发制人跟踪)。

我们的版本是 2014,但对更高版本的回答也很有用。

sql-server

8
推荐指数
1
解决办法
367
查看次数

保持日志文件大于数据文件是否正常?

保持日志文件大于数据文件是否正常?

我知道为什么我的日志文件很大,这是因为我在特定时间发生了巨大的修改和锁定,导致我的日志文件很大..因为我使用日志传送,我通常每 10 次进行日志备份分钟。

我要问的是“看到日志文件大于数据文件是否正常,因为我的数据文件大约为 7,216 GB,而我的日志文件大约为 9,930 GB?” 恐怕日志和数据文件之间存在标准比例?我不想缩小我的日志文件,因为我的硬盘上有足够的空间。

sql-server sql-server-2008-r2

8
推荐指数
2
解决办法
2147
查看次数

用子查询替换长 GROUP BY 列表

这是我在 Stack Overflow 上的问题的转贴。他们建议在这里问:

我在2005 年找到了一篇在线文章,作者声称,许多开发人员使用 GROUP BY 是错误的,您最好将其替换为子查询。

我已经在我的一个查询中对其进行了测试,我需要根据另一个表中连接条目的数量对搜索结果进行排序(更常见的条目应该首先出现)。我最初的经典方法是将两个表连接到一个公共 ID,按选择列表中的每个字段分组,并按子表的计数对结果进行排序。

现在,来自链接博客的 Jeff Smith 声称,您最好使用一个子选择,它执行所有分组,而不是加入该子选择。检查这两种方法的执行计划,SSMS 指出,大组需要 52% 的时间,子选择需要 48%,所以从技术角度来看,子选择方法实际上要快一点。但是,“改进”的 SQL 命令似乎生成了更复杂的执行计划(就节点而言)

你怎么认为?您能否详细说明在这种特定情况下如何解释执行计划,以及哪一个通常是更可取的选择?

SELECT
    a.ID,
    a.ID_AddressType,
    a.Name1,
    a.Name2,
    a.Street,
    a.Number,
    a.ZipCode,
    a.City,
    a.Country
FROM dbo.[Address] a
INNER JOIN CONTAINSTABLE(
    dbo.[Address],
    FullAddress,
    '"ZIE*"',
    5
) s ON a.ID = s.[KEY]
LEFT JOIN dbo.Haul h ON h.ID_DestinationAddress = a.ID
GROUP BY
    a.ID,
    a.ID_AddressType,
    a.Name1,
    a.Name2,
    a.Street,
    a.Number,
    a.ZipCode,
    a.City,
    a.Country,
    s.RANK
ORDER BY s.RANK DESC, COUNT(*) DESC;

SELECT
    a.ID,
    a.ID_AddressType,
    a.Name1, …
Run Code Online (Sandbox Code Playgroud)

join sql-server subquery

8
推荐指数
1
解决办法
1552
查看次数

使用命令 XTP_DB_RECOVERY 的数据库卡在“恢复中”

我们最近将表转换为内存优化数据。我们的备份已经全部膨胀(3x300GB 文件到 3x600GB 的完整文件,3x50GB 到 3x250GB 的差异文件),并且启动越来越慢。

为了避免这些问题,我们将有问题的表转换为 SCHEMA_ONLY 持久性,但现在数据库不会离开“恢复中”状态。

错误日志最初每 20 秒更新一次恢复状态,预测分析需要大约 9 天才能完成,但是大约一个小时后,更新停止了。

SP_WHO2 显示只有一个进程使用命令访问有问题的数据库XTP_DB_RECOVERY,但不SELECT * FROM sys.dm_db_xtp_checkpoint_files返回任何行。

我有什么办法吗?或者如何查看此XTP_DB_RECOVERY命令的估计剩余时间?

sql-server recovery memory-optimized-tables

8
推荐指数
1
解决办法
757
查看次数