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
    • 最新
    • 标签
主页 / dba / 问题 / 249182
Accepted
Randi Vertongen
Randi Vertongen
Asked: 2019-09-20 06:08:27 +0800 CST2019-09-20 06:08:27 +0800 CST 2019-09-20 06:08:27 +0800 CST

稀疏列、cpu 时间和过滤索引

  • 772

稀疏

在对稀疏列进行一些测试时,正如您所做的那样,我想知道直接原因是性能受挫。

DDL

我创建了两张相同的表,一张有 4 个稀疏列,一张没有稀疏列。

--Non Sparse columns table & NC index
CREATE TABLE dbo.nonsparse( ID INT IDENTITY(1,1) PRIMARY KEY NOT NULL,
                      charval char(20) NULL,
                      varcharval varchar(20) NULL,
                      intval int NULL,
                      bigintval bigint NULL
                      );
CREATE INDEX IX_Nonsparse_intval_varcharval
ON dbo.nonsparse(intval,varcharval)
INCLUDE(bigintval,charval);

-- sparse columns table & NC index

CREATE TABLE dbo.sparse( ID INT IDENTITY(1,1) PRIMARY KEY NOT NULL,
                      charval char(20) SPARSE NULL ,
                      varcharval varchar(20) SPARSE NULL,
                      intval int SPARSE NULL,
                      bigintval bigint SPARSE NULL
                      );

CREATE INDEX IX_sparse_intval_varcharval
ON dbo.sparse(intval,varcharval)
INCLUDE(bigintval,charval);

DML

然后我在两者中插入了大约2540 个非空值。

INSERT INTO dbo.nonsparse WITH(TABLOCK) (charval, varcharval,intval,bigintval)
SELECT 'Val1','Val2',20,19
FROM MASTER..spt_values;

INSERT INTO dbo.sparse WITH(TABLOCK) (charval, varcharval,intval,bigintval)
SELECT 'Val1','Val2',20,19
FROM MASTER..spt_values;

之后,我在两个表中都插入了1M NULL值

INSERT INTO dbo.nonsparse WITH(TABLOCK)  (charval, varcharval,intval,bigintval)
SELECT TOP(1000000) NULL,NULL,NULL,NULL 
FROM MASTER..spt_values spt1
CROSS APPLY MASTER..spt_values spt2;

INSERT INTO dbo.sparse WITH(TABLOCK) (charval, varcharval,intval,bigintval)
SELECT TOP(1000000) NULL,NULL,NULL,NULL 
FROM MASTER..spt_values spt1
CROSS APPLY MASTER..spt_values spt2;

查询

非稀疏表执行

在新创建的非稀疏表上运行此查询两次时:

SET STATISTICS IO, TIME ON;
SELECT  * FROM dbo.nonsparse
WHERE   1= (SELECT 1) -- force non trivial plan
OPTION(RECOMPILE,MAXDOP 1);

逻辑读取显示5257页

(1002540 rows affected)
Table 'nonsparse'. Scan count 1, logical reads 5257, physical reads 0, read-ahead reads 0, lob logical reads 0, lob physical reads 0, lob read-ahead reads 0.

cpu时间为343 ms

 SQL Server Execution Times:
   CPU time = 343 ms,  elapsed time = 3850 ms.

稀疏表执行

在稀疏表上运行相同的查询两次:

SELECT  * FROM dbo.sparse
WHERE   1= (SELECT 1) -- force non trivial plan
OPTION(RECOMPILE,MAXDOP 1);

读数较低,1763

(1002540 rows affected)
Table 'sparse'. Scan count 1, logical reads 1763, physical reads 3, read-ahead reads 1759, lob logical reads 0, lob physical reads 0, lob read-ahead reads 0.

但是 cpu 时间更高,547 ms。

 SQL Server Execution Times:
   CPU time = 547 ms,  elapsed time = 2406 ms.

稀疏表执行计划

非稀疏表执行计划


问题

原始问题

由于NULL值不直接存储在稀疏列中,cpu 时间的增加可能是由于将NULL值作为结果集返回吗?还是仅仅是文档中所述的行为?

稀疏列减少了空值的空间需求,但代价是检索非空值的开销更大

还是仅与使用的读取和存储有关的开销?

即使使用执行后丢弃结果选项运行 ssms,与非稀疏选择(219 毫秒)相比,稀疏选择的 CPU 时间(407 毫秒)更高。

编辑

即使只有 2540 个存在,它也可能是非空值的开销,但我仍然不相信。

这似乎是大致相同的性能,但稀疏因素丢失了。

CREATE INDEX IX_Filtered
ON dbo.sparse(charval,varcharval,intval,bigintval)
WHERE charval IS NULL  
      AND varcharval IS NULL
      AND intval  IS NULL
      AND bigintval  IS NULL;

CREATE INDEX IX_Filtered
ON dbo.nonsparse(charval,varcharval,intval,bigintval)
WHERE charval IS NULL  
      AND varcharval IS NULL
      AND intval  IS NULL
      AND bigintval  IS NULL;


    SET STATISTICS IO, TIME ON;

SELECT  charval,varcharval,intval,bigintval FROM dbo.sparse WITH(INDEX(IX_Filtered))
WHERE charval IS NULL AND  varcharval IS NULL
                     AND intval  IS NULL
                     AND bigintval  IS NULL
                     OPTION(RECOMPILE,MAXDOP 1);


SELECT  charval,varcharval,intval,bigintval 
FROM dbo.nonsparse WITH(INDEX(IX_Filtered))
WHERE charval IS NULL AND 
                      varcharval IS NULL
                     AND intval  IS NULL
                     AND bigintval  IS NULL
                     OPTION(RECOMPILE,MAXDOP 1);

似乎有大约相同的执行时间:

 SQL Server Execution Times:
   CPU time = 297 ms,  elapsed time = 292 ms.

 SQL Server Execution Times:
   CPU time = 281 ms,  elapsed time = 319 ms.

但是为什么现在逻辑读取量相同?除了包含的 ID 字段和其他一些非数据页面之外,稀疏列的过滤索引不应该不存储任何内容吗?

Table 'sparse'. Scan count 1, logical reads 5785,
Table 'nonsparse'. Scan count 1, logical reads 5785

以及两个指数的大小:

RowCounts   Used_MB Unused_MB   Total_MB
1000000     45.20   0.06        45.26

为什么这些大小一样?稀疏性消失了吗?

使用过滤索引时的两个查询计划


额外信息

select @@version

Microsoft SQL Server 2017 (RTM-CU16) (KB4508218) - 14.0.3223.3 (X64) 2019 年 7 月 12 日 17:43:08 版权所有 (C) 2017 Microsoft Corporation Developer Edition (64-bit) o​​n Windows Server 2012 R2 Datacenter 6.3 (Build 9600:)(管理程序)

在运行查询并仅选择ID字段时,cpu 时间是可比的,稀疏表的逻辑读取较低。

桌子的大小

SchemaName  TableName   RowCounts   Used_MB Unused_MB   Total_MB
dbo         nonsparse   1002540     89.54   0.10        89.64
dbo         sparse      1002540     27.95   0.20        28.14

当强制使用聚集索引或非聚集索引时,cpu 时间差仍然存在。

sql-server sql-server-2017
  • 1 1 个回答
  • 418 Views

1 个回答

  • Voted
  1. Best Answer
    Josh Darnell
    2019-09-20T09:35:29+08:002019-09-20T09:35:29+08:00

    还是仅仅是文档中所述的行为?

    似乎是这样。文档中提到的“开销”似乎是 CPU 开销。

    分析这两个查询,稀疏查询采样了 367 毫秒的 CPU,而非稀疏查询有 284 毫秒的 CPU。这是 83 毫秒的差异。

    Perfview 的屏幕截图显示了运行查询的线程的总 CPU

    大部分在哪里?

    两个配置文件看起来非常相似,直到它们到达sqlmin!IndexDataSetSession::GetNextRowValuesInternal. 此时,稀疏代码沿着运行的路径向下运行sqlmin!IndexDataSetSession::GetDataLong,该路径调用了一些看起来与稀疏列特征 ( HasSparseVector, StoreColumnValue) 相关的函数,并且加起来为 (42 + 11 =) 53 毫秒。

    稀疏列的 CPU 差异屏幕截图

    为什么这些大小一样?稀疏性消失了吗?

    是的,当稀疏列用作索引键时,稀疏存储优化似乎不会延续到非聚集索引。因此,非聚集索引键列无论是否稀疏都会占用其完整大小,但如果包含的列稀疏且为 NULL,则包含的列占用零空间。

    查看DBCC PAGE具有 NULL 值稀疏列的聚集索引页的输出,我可以看到记录长度为 11(ID 为 4,标准每记录开销为 7):

    Record Type = PRIMARY_RECORD        Record Attributes =  NULL_BITMAP    Record Size = 11
    

    对于过滤后的索引,记录始终为 40,即所有键列的大小之和(4 字节 ID + 20 字节 charval + 4 字节 varcharval + 4 字节 intval + 8 字节 big intval = 40 字节)。

    出于某种原因,DBCC PAGE不包括索引记录的“记录大小”中的 7 字节开销:

    Record Type = INDEX_RECORD          Record Attributes =  NULL_BITMAP    Record Size = 40
    

    未过滤的索引大小更小(4 字节 ID + 4 字节 intval + 4 字节 varcharval = 12 字节),因为其中两个稀疏列是包含列,这再次获得了稀疏优化:

    Record Type = INDEX_RECORD          Record Attributes =  NULL_BITMAP    Record Size = 12
    

    我猜这种行为差异符合文档页面中列出的限制之一:

    稀疏列不能是聚集索引或唯一主键索引的一部分

    它们被允许作为非聚集索引中的键,但它们不会被存储,呃,稀疏的。

    • 7

相关问题

  • SQL Server - 使用聚集索引时如何存储数据页

  • 我需要为每种类型的查询使用单独的索引,还是一个多列索引可以工作?

  • 什么时候应该使用唯一约束而不是唯一索引?

  • 死锁的主要原因是什么,可以预防吗?

  • 如何确定是否需要或需要索引

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