小编db2*_*db2的帖子

在触发器中加入 INSERTED 和 DELETED 表的糟糕性能

我在表上有一个 UPDATE 触发器,用于监视从一个特定值更改为任何其他值的特定列。发生这种情况时,它会通过单个 UPDATE 语句更新另一个表中的一些相关数据。

触发器所做的第一件事是检查是否有任何更新的行的该列的值与相关值发生了变化。它只是将 INSERTED 连接到 DELETED 并比较该列中的值。如果没有任何条件,它会提前退出,因此 UPDATE 语句不会运行。

IF NOT EXISTS (
    SELECT TOP 1 i.CUSTNMBR
    FROM INSERTED i
        INNER JOIN DELETED d
            ON i.CUSTNMBR = d.CUSTNMBR
    WHERE d.CUSTCLAS = 'Misc'
        AND i.CUSTCLAS != 'Misc'
)
    RETURN
Run Code Online (Sandbox Code Playgroud)

在这种情况下,CUSTNMBR 是基础表的主键。如果我对此表进行大量更新(例如 5000 多行),即使我没有触及 CUSTCLAS 列,该语句也需要 AGES。我可以在 Profiler 中看到它在这个语句上停滞了几分钟。

执行计划很奇怪。它显示了具有 3,714 次执行和约 1,850 万行输出的插入扫描。它通过 CUSTCLAS 列上的过滤器运行。它将这个(通过嵌套循环)连接到一个删除扫描(也在 CUSTCLAS 上过滤),它只执行一次并且有 5000 个输出行。

我在这里做了什么愚蠢的事情来导致这种情况?请注意,触发器绝对必须正确处理多行更新。

编辑

我也尝试过这样写(以防 EXISTS 做了一些不愉快的事情),但它仍然一样糟糕。

DECLARE @CUSTNMBR varchar(31)
SELECT TOP 1 @CUSTNMBR = i.CUSTNMBR
FROM INSERTED i
    INNER …
Run Code Online (Sandbox Code Playgroud)

trigger sql-server-2008 sql-server

13
推荐指数
2
解决办法
1万
查看次数

我可以通过恢复 MASTER 数据库来恢复 TDE 证书吗?

(幸运的是,我们目前并未处于这种情况,只是提前计划,看看如果发生这种情况,我们的选择是什么。)

对于使用透明日期加密 (TDE) 加密的数据库,除非您有用于加密它的证书的备份,否则数据库备份的副本是不可恢复的。

如果你没有那个怎么办?还有其他选择吗?

如果整个服务器发生故障,在新硬件上恢复 MASTER 数据库的备份是否也会恢复证书?

sql-server encryption transparent-data-encryption disaster-recovery

10
推荐指数
2
解决办法
6520
查看次数

出于存档目的对数据库进行碎片整理/压缩的最佳方法

我们有一个用于电子邮件归档的 SQL Server 实例(由 3rd 方归档包提供)。每隔一段时间,软件就会滚动到一个新的空数据库。我们过去每季度进行一次,但现在我们希望每月进行一次。每月存档的数据量约为 15 - 20 GB,大部分数据仅驻留在少数表中(通常为 2 - 4 个)。

一旦我们滚动到一个新数据库,旧数据库就会严格按照只读方式使用。我想做的是将它优化成一个漂亮的、紧凑的数据文件,所有的表/索引都是连续的并且具有非常高的填充因子,并且数据文件末尾没有太多的空白空间。此外,我们在这台服务器上使用标准版,但存在所有隐含的限制(否则我已经在使用数据压缩了)。

我能想到的几种可能性:

  1. REBUILD/REORGANIZE 索引、DBCC SHRINKFILE(好吧,这不是一个明智的选择,因为 DBCC SHRINKFILE 会将它接触到的任何东西都分割开来,但为了完整起见,我将其包括在内。)
  2. 创建一个关闭自动统计的新数据库。编写脚本并从源数据库重新创建所有表。使用 bcp 按集群键顺序将数据导出/导入到新数据库中。编写脚本并重新创建所有索引。使用完整扫描重新计算所有统计信息。
  3. 创建一个关闭自动统计的新数据库。编写脚本并从源数据库重新创建所有表。使用 SSIS 或 T-SQL 将数据传输到新数据库。编写脚本并重新创建所有索引。使用完整扫描重新计算所有统计信息。

每种情况下的最后一步都是将数据库设置为只读模式。

这样做还有哪些其他好的/更好的选择?我关心的是以这样一种方式移动数据,以保持高填充因子,并以逻辑上连续的方式。

编辑:

我应该提到大约 75% 的数据似乎存储在图像 (LOB) 列中。

sql-server sql-server-2012

9
推荐指数
1
解决办法
1037
查看次数

ORDER BY和字母数字混合串的比较

我们需要对通常是需要“自然”排序的数字和字母混合字符串的值进行一些报告。诸如“P7B18”或“P12B3”之类的东西。@字符串将主要是字母序列然后数字交替。但是,这些段的数量和每个段的长度可能会有所不同。

我们希望这些数字部分按数字顺序排序。显然,如果我直接用 处理这些字符串值ORDER BY,那么“P12B3”将在“P7B18”之前出现,因为“P1”早于“P7”,但我希望相反,因为“P7”自然在前面“P12”。

我还希望能够进行范围比较,例如@bin < 'P13S6'或类似的。我不必处理浮点数或负数;这些将严格是我们正在处理的非负整数。字符串长度和段数可能是任意的,没有固定的上限。

在我们的例子中,字符串大小写并不重要,但如果有一种方法可以以排序方式感知方式做到这一点,其他人可能会发现这很有用。所有这一切中最丑陋的部分是我希望能够在WHERE子句中进行排序和范围过滤。

如果我在 C# 中执行此操作,这将是一项非常简单的任务:进行一些解析以将 alpha 与数字分开,实现 IComparable,您基本上就完成了。当然,SQL Server 似乎没有提供任何类似的功能,至少就我所知。

任何人都知道使这项工作有什么好的技巧吗?是否有一些很少公开的能力来创建实现 IComparable 的自定义 CLR 类型并使其按预期运行?我也不反对 Stupid XML Tricks(另请参阅:list concatenation),而且我在服务器上也提供了 CLR 正则表达式匹配/提取/替换包装函数。

编辑: 作为一个更详细的例子,我希望数据表现得像这样。

SELECT bin FROM bins ORDER BY bin

bin
--------------------
M7R16L
P8RF6JJ
P16B5
PR7S19
PR7S19L
S2F3
S12F0
Run Code Online (Sandbox Code Playgroud)

即将字符串分成所有字母或所有数字的标记,并分别按字母或数字对它们进行排序,最左边的标记是最重要的排序项。就像我提到的,如果您实现 IComparable,在 .NET 中是小菜一碟,但我不知道如何(或是否)您可以在 SQL Server 中执行此类操作。这肯定不是我在 10 年左右的工作中遇到过的事情。

sql-server collation sql-server-2012 sorting natural-sort

9
推荐指数
1
解决办法
7401
查看次数

日志卷的最佳块/条带大小?

我知道 SQL Server 中数据量的常见建议是使用 64 KB 块/条带,因为 I/O 通常由整个范围完成。但是,我找不到有关日志文件 I/O 的任何好的信息。

我一直在 Process Monitor 中观察 I/O 活动,看来日志文件 I/O 大小范围从 512 字节到略低于 64 KB。我猜这取决于正在记录的事务的大小,并且使用多个 ~64 KB 写入将大事务拆分。

因此,假设我将分区与 RAID 条带对齐,假设 64 KB 块/条带将产生最佳性能,所有其他条件相同,是否安全?我预计较小的事务,即具有 512 字节写入的事务,不会因为大块大小惩罚而产生重大影响,而大得多的事务快速连续写入大量 64 KB 块会更重要的是调整。

sql-server-2008 sql-server

7
推荐指数
2
解决办法
5820
查看次数

防止数据源部署在指定文件夹之外

在我继续对 Catalog 表设置一个非常糟糕的检查约束之前,我想先征求一些更好的想法。

我想确保我们的报表服务器上的所有共享数据源都部署到“/Data Sources”。时不时,我们会错误地将一个部署到其他目录(特别是如果它是从 SSRS 2000 升级的报告,它不允许指定不同的数据源部署位置)。

Type != 5 OR ParentID = 'GUID of /Data Sources directory'如果归结为它,我可以在 Catalog(或类似的)上放置一个丑陋的检查约束,但如果有更好的选择,我宁愿使用它。

sql-server-2008 sql-server ssrs

7
推荐指数
1
解决办法
908
查看次数

对超大表进行分区/索引

我正在对大约 500 GB 的单个数据仓库表进行索引和分区。该表是一个堆,有一百多个TEXT列,并且TEXT_IN_ROW启用了该选项。这张桌子不是我设计的,我也没有能力在不久的将来改变它。

我的任务是对其进行分区。我们正在使用测试服务器上的数据库副本来解决这个问题。它每秒可以将大约 2 GB 的数据推送到 SSD RAID 阵列,因此 I/O 不是一个明显的瓶颈,它有 16 个内核(2 个 NUMA 节点)和 64 GB 的 RAM。

我的方法是禁用所有非聚集索引,创建分区函数和分区方案(大约 12 个分区,都在PRIMARY文件组上 - 他们使用它来启用滚动维护并为每晚 ETL 提供更多本地化插入,而不是分发我/O),然后使用此分区方案为表构建聚集索引。

我正在创建聚集索引并对表进行分区,如下所示:

CREATE CLUSTERED INDEX CX_DailyTable ON DailyTable (LoadDate, SeqNumber) 
  WITH (SORT_IN_TEMPDB = ON) ON monthly_on_primary (LoadDate)
Run Code Online (Sandbox Code Playgroud)

显然,这需要很长时间(到目前为止是 3 小时),而且我当然不希望它很快。让我稍微担心的是 tempdb 现在正在推动近 1 TB 并稳步攀升,尽管当前表的大小大约是这个大小的一半。我读过的 MS 文档建议 tempdb 空间使用量应该与最终表/聚集索引的大小有关。

http://msdn.microsoft.com/en-us/library/ms188281.aspx

如果 SORT_IN_TEMPDB 设置为 ON,则 tempdb 中必须有足够的可用空间来存储排序运行,并且目标文件组中必须有足够的可用空间来存储最终索引结构。排序运行包含索引的叶行。

他们的估计不正确吗?tempdb 是否不仅仅用于排序运行?或者创建这个聚集索引以某种方式使表的大小加倍?(似乎不太可能;这是一个相当宽的表,我估计每行可以获得额外的 4-8 个字节,加上通过添加聚集索引获得的非叶页。)

sql-server sql-server-2008-r2

7
推荐指数
1
解决办法
4181
查看次数

向从任何主机连接的用户授予表权限

我有一个用户帐户——我们称之为“wordpress”——我需要允许访问同一服务器上另一个电子商务数据库中的一些目录表。我已经为用户配置了三个允许连接的主机掩码:'localhost'、Web 服务器的 IP 地址和 Web 服务器的主机名。没有问题。

'wordpress' 用户还可以完全访问自己的数据库,这是通过 MySQL Workbench 中的 Schema Privileges 部分授予的。在这里,它显示主机是“%”,这正是我想要的,因为我不想为同一用户管理三组重复的权限。如果我查看 mysql.db,我会看到这些权限,在 Host 列中带有“%”。

所以现在我想对另一个数据库中的几个表授予 SELECT 权限 - 我们称之为“存储”。所以我试试这个:

GRANT SELECT ON store.catalog TO 'wordpress'@'%';
Run Code Online (Sandbox Code Playgroud)

我得到“在用户表中找不到任何匹配的行”,原因很明显,“%”不是我明确允许此特定用户建立连接的主机掩码。那么从任何允许的主机掩码向用户授予表权限的正确语法是什么?MySQL Workbench 是如何获得架构权限的?我不必手动将行插入到 mysql.tables_priv 中,对吗?

更新:为了澄清,这是当前用户/授权表的样子。很明显,我已经匿名了一些名字。请注意,架构权限表中的主机是“%”,但该主机没有任何用户。我如何让 MySQL 允许我使用模式对象授权来做到这一点?最好不要直接在 mysql.tables_priv 中乱搞,但如果归结为它,我会这样做。

mysql> SELECT user, host FROM mysql.user WHERE user = 'wordpress';
+-----------+-----------+
| user      | host      |
+-----------+-----------+
| wordpress | 10.0.0.22 |
| wordpress | webserver |
| wordpress | localhost |
+-----------+-----------+
3 rows in set (0.00 sec)

mysql> SELECT …
Run Code Online (Sandbox Code Playgroud)

mysql authentication mysql-5.5

6
推荐指数
1
解决办法
5万
查看次数

按需模糊查找

我们有一个客户表(谁没有?),其中包含许多从业务角度来看是重复的记录。我已经能够创建一个 SSIS 包来执行模糊分组,并报告潜在的重复项。

现在,假设我想在有人进入新客户时进行这种分析。这个想法是对客户名称(可能还有一些其他基本信息,如邮政编码)执行模糊查找,并在继续客户创建表单之前显示潜在的重复项。

这里明显的问题是模糊分组和查找组件是 SSIS 的一部分。如果我想按需运行那些,我必须做一些疯狂的事情,比如将搜索词放在临时表中,运行 SSIS 包,等待它完成,并从输出表中获取结果。这会很慢,很痛苦,并且有严重的并发问题。

因此,另一个想法是使用全文索引。在试用它时,它看起来不合适。它无法捕捉到客户名称的细微拼写错误,或“Company”与“Corporation”与“Co.”或“Anderson”与“Andersen”以及其他此类变体的名称不同的名称。

有没有什么东西可以让 T-SQL 灵活地进行模糊分组/匹配?我可以通过模糊查找来保存标记,但看起来我仍然需要重新实现大部分匹配算法才能使用它们。

sql-server-2008 sql-server ssis

6
推荐指数
1
解决办法
6136
查看次数

为现有的 AlwaysOn 数据库启用 TDE

我需要对 AlwaysOn 进行一些基准测试,无论是否启用 TDE。我看到的所有说明都涉及将加密数据库添加到可用性组,但我没有提到为 AG 中已有的数据库启用加密。

我可以将服务器证书恢复到所有节点,然后从主节点启用 TDE 吗?我希望我不需要从 AG 中删除数据库,对其进行加密,然后重新初始化所有节点,因为数据库大约为 100 GB。如果需要,我们可以这样做,但这肯定会减慢我们的测试速度。

更新

我只是在一些实验室虚拟机上尝试过这个。我能够在主节点上创建一个证书,在所有辅助节点上恢复它,然后使用这个证书在主节点上创建一个数据库加密密钥。之后我所要做的就是ALTER DATABASE AdventureWorks SET ENCRYPTION ON在主服务器上,一两分钟后,sys.dm_database_encryption_keys 在所有节点上都显示了 encryption_state = 3。

那么,后续问题:是否有任何理由认为我不应该使用此程序?SQL Server 似乎对结果很满意,但我还没有看到任何地方讨论过这种方法。在处理加密和高可用性问题时,我不想让事情碰运气。

sql-server sql-server-2012 availability-groups transparent-data-encryption

6
推荐指数
1
解决办法
2147
查看次数