我在 SQL Server 2016 中有三个聚集列存储索引 (CCI) 表。所有这些 CCI 都在相同的分区方案中,基于租户 ID。最近,不一致的是,我在从连接到这些表的简单选择语句上遇到了死锁。死锁的示例查询:
SELECT TOP 33 r.tenantid
FROM Table_r r
INNER JOIN Table_cm cm ON r.MyKey=cm.MyKey
INNER JOIN Table_pe pe ON r.MyKey=pe.MyKey
WHERE r.TenantId = 69
AND pe.TenantId = 69
AND cm.TenantId = 69
Run Code Online (Sandbox Code Playgroud)
错误信息:
事务(进程 ID 56)在与另一个进程的通用可等待对象资源上发生死锁,并已被选为死锁受害者。重新运行事务。
线索:
sql-server deadlock partitioning columnstore sql-server-2016
我有一个由四个聚集列存储索引表 (CCI) 和九个行存储表组成的数据仓库。这些表仅用于分析,并且每 15 分钟从临时表中插入 CCI 数据。我希望通过添加分区和排序来优化查询性能。
该数据的所有查询都基于一个包含大约 350 个不同值的整数字段。最左边的 CCI 有 100M 条记录和 125 列。有三个子 CCI 具有相同的整数字段。CCI 2 有 1500 万条记录和 150 列,CCI 3 和 4 都有大约 3000 万条记录和 25 列。
在这 350 个不同的整数中,最左边表中的记录数分布如下:
此外,还有其他九个行存储表也连接到 CCI。它们具有涓流插入,是 CCI 的子项,它们都包含相同的整数字段。这些行存储具有相似或更小的记录量,每个 < 10 列,两个包含 LOBS,两个经常进行大规模更新(这些更新也基于 ID 字段)。
我应该做多少个分区?
我还应该对行存储表进行分区吗?
是否有我忽略的重要考虑因素?
关于我之前提到的“排序”的注意事项:
最左边的 CCI 中的日期字段通常是这些查询中的次要谓词,因此我正在考虑每四个星期左右按日期重新排序 CCI 作为维护。我将通过删除 CCI、在日期上添加聚集行存储索引、删除该索引,然后使用 MAXDOP=1 重新添加 CCI 来实现这种排序。我也在考虑通过其父级的连接键对子 CCI 进行排序。
我正在为新的数据仓库设计 ERD。
我将“事实”放在引号中并说“松散星型模式”,因为使用聚集列存储,我可以将许多维度直接放入“事实”表中,而无需担心行宽的典型问题。我的许多维度都进入了“事实”表。我正在创建一些维度表和代理键,但前提是除了暗淡描述本身之外,暗淡还具有属性。
这给我带来了一些非常广泛、高基数的领域,即nvarchar(max). 不必太深入,将这些字段视为非规范化列表。我需要针对我的一个数据源的粒度对列表进行非规范化。我确实在另一个事实表中对其进行了规范化,但不是我在此数据源中出现的事实表。
用户需要这些字段来搜索我正在显示的数据集市中的关键字。在我当前的设计中,它们位于聚集列存储“事实”表中。用户将经常查询事实表而不触及nvarchar(max)字段。
有没有比聚集列存储表更正确的将宽维度放入我的数据仓库的地方?
Joe Obbish告诉我,我们目前无法放入nvarchar(max)CCI。创建一个 LOB 表作为我的“事实”表的扩展对我来说是最佳实践吗?
我们将来可能会添加其他语言。目前和在可预见的期限内,该nvarchar栏仅包含英语。
data-warehouse database-design sql-server columnstore sql-server-2016
我想在一些非常大的宽表上实现(SQL Server 2014)聚集列存储索引。我需要更多内存来支持这个吗?如果是这样,我如何确定多少?
我在我的报告数据库中使用 MS SQL Server 2016 聚集列存储索引(我们称之为 CCI)。
在最初的设计中,我考虑的是星型模式,但后来我开始使用 CCI。现在我放弃了许多维度表,转而将字符串直接展平到“事实”表中。我保留维度表的唯一地方是当该维度具有频繁更改的属性并且要求使更改的属性适用于所有历史记录时。我做了这么多让一位拥有更多 DW 经验但没有空闲时间探索 CCI 的同事感到沮丧。
似乎作为单独列存储在磁盘上的平面表(以及提供的大规模压缩)根本不需要很窄。使用 CCI 时,何时还需要维度表?
data-warehouse database-design sql-server columnstore star-schema
我的研究表明,我可以在短时间内删除表中的一列(前提是我获得了排他锁),因为这只是元数据更改。
该表有两个不同的服务,不断插入和更新记录。太热了。如果不开发这种活动级别的完整复制环境,我怎么能确保像这样的陈述
ALTER TABLE x DROP COLUMN y
Run Code Online (Sandbox Code Playgroud)
会成功获得排他锁,快速做drop,然后解锁表吗?
SQL Server 将如何将此请求排队(例如,先进先出)?我能确定 DROP COLUMN 真的只需要几分钟吗?
在 PROD 中长时间锁定此表是不可接受的,因此我试图避免出现意外。
其他注意事项:稍后我将在线重新索引以对索引进行碎片整理并回收空间。
目标:
删除三个表中数十亿条旧记录(大约 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 吗?
我正在对我们的开发数据库进行干净的备份,以便轻松地重新启动数据库。该数据库有大约 200 个测试用户,应该将其删除以使其真正干净,但问题是我无法删除其中任何一个。
当我运行如下命令时:
DROP USER [MyGarbageUser]
Run Code Online (Sandbox Code Playgroud)
它提示我以下错误:
消息 15284,级别 16,状态 1,第 5 行 数据库主体已授予或拒绝对数据库中的对象的权限,无法删除。
这些用户既不拥有该数据库中的任何对象(据我所知),也不应该拥有。在网上搜索了一大堆后,我仍然无法找到解决方案。
如何强制从该数据库中删除 MyGarbageUser?
sql-server ×8
columnstore ×5
delete ×2
locking ×2
partitioning ×2
deadlock ×1
index ×1
star-schema ×1
users ×1