如果我知道字段的格式正确,我应该为所有这些字段创建检查约束,还是会影响插入/更新的性能?将正则表达式用于复杂规则是一个好主意,还是应该只使用像case和length这样的简单约束?
这些字段已在应用程序级别进行验证。
答案 0 :(得分:9)
通常,最好不要信任应用程序并使用检查约束。数据必须保持完整性(谁知道可能运行的流氓脚本,或者可能漏掉的程序错误)。
但是,如果您有许多复杂的检查约束,并且您注意到插入/更新速度减慢,则可能需要重新评估。是否真的有必要在每个领域都有一个?不可以。列数据类型和长度也是约束条件。
答案 1 :(得分:7)
Quassnoi的观点是有效的,但值得记住的是并非所有CHECK
约束都相同。在以下测试中,我将REGEXP_LIKE()
检查与另外两个“老式”检查进行了基准测试;第一个将值转换为零字符串,然后进行相等性检查,第二个使用BETWEEN()
进行范围检查。
“挂钟”测试对环境条件敏感(例如检查点点火),因此我们需要多次运行它们。另外要记住的是,性能因版本而异。例如,我正在运行11g并且正则表达式检查始终以 9-10秒运行,这表明Oracle自10g以来已经对其进行了相当大的优化。另一方面,未经检查的插入在 1.7 - 2 -hh秒运行,因此正则表达式仍然相对昂贵。其他支票的评分约为 2.5 - 3.0秒,这对诚信度的影响大约为50%。
是否值得付出代价实际上取决于您对数据的看法。经验说依靠客户端来强制执行数据规则不可避免地意味着在某些时候规则将被破坏。或者是因为开发人员省略了应用它们或从应用程序中删除它们。或者因为有人在数据库中附加了一个新的客户端应用程序(例如批量上载,Web服务),但不包括这些规则。
最后,大多数应用程序不会一次加载一百万行。与网络往返相比,将检查应用于单个插入或上载所需的微秒可能是一个微不足道的开销。
SQL> CREATE TABLE t_check (value VARCHAR2(50))
2 /
Table created.
Elapsed: 00:00:00.01
SQL>
SQL> INSERT
2 INTO t_check
3 SELECT level
4 FROM dual
5 CONNECT BY
6 level <= 1000000
7 /
1000000 rows created.
Elapsed: 00:00:01.68
SQL>
SQL> prompt Regex check
Regex check
SQL>
SQL> drop table t_check
2 /
Table dropped.
Elapsed: 00:00:00.37
SQL> CREATE TABLE t_check (value VARCHAR2(50) NOT NULL
2 , CHECK(REGEXP_LIKE(value, '^[0-9]{1,10}$')))
3 /
Table created.
Elapsed: 00:00:00.07
SQL>
SQL> INSERT
2 INTO t_check
3 SELECT level
4 FROM dual
5 CONNECT BY
6 level <= 1000000
7 /
1000000 rows created.
Elapsed: 00:00:09.53
SQL>
SQL> prompt old fashioned "mask" check
old fashioned "mask" check
SQL>
SQL> drop table t_check
2 /
Table dropped.
Elapsed: 00:00:00.59
SQL> CREATE TABLE t_check
2 (value VARCHAR2(50) NOT NULL
3 , CHECK(translate(lpad(value, 20, '0')
4 , '1234567890', '0000000000') = '00000000000000000000' ))
5 /
Table created.
Elapsed: 00:00:00.01
SQL>
SQL> INSERT
2 INTO t_check
3 SELECT level
4 FROM dual
5 CONNECT BY
6 level <= 1000000
7 /
1000000 rows created.
Elapsed: 00:00:02.82
SQL>
SQL> prompt old fashioned "range" check
old fashioned "range" check
SQL>
SQL> drop table t_check
2 /
Table dropped.
Elapsed: 00:00:00.39
SQL> CREATE TABLE t_check
2 (value VARCHAR2(50) NOT NULL
3 , CHECK( value between 1 and 1000000))
4 /
Table created.
Elapsed: 00:00:00.01
SQL>
SQL> INSERT
2 INTO t_check
3 SELECT level
4 FROM dual
5 CONNECT BY
6 level <= 1000000
7 /
1000000 rows created.
Elapsed: 00:00:02.23
SQL>
答案 2 :(得分:1)
这取决于你的偏执程度。
当然,双重检查优于单一检查,但客户端的检查具有优势或并行性。
客户端检查由客户端使用的许多(可能是数千台)计算机执行,而服务器端检查由单个服务器执行。
我只是在我的Oracle 10g
:
CREATE TABLE t_check (value VARCHAR2(50) NOT NULL, CHECK(REGEXP_LIKE(value, '^[0-9]{1,10}$')))
INSERT
INTO t_check
SELECT level
FROM dual
CONNECT BY
level <= 1000000
使用CHECK
,运行27
秒,没有一个,只需2
秒。
如果这对您来说是和的问题,如果您完全确定除非经过客户端软件检查,否则任何值都不会进入您的数据库,那么请依赖客户端。
答案 3 :(得分:1)
“这取决于你的偏执程度。
当然,双重检查优于单一检查,但客户端的检查具有优势或并行性。
客户端检查由客户端使用的许多(可能是数千台)计算机执行,而服务器端检查由单个服务器执行。“
虽然这些都不是不真实的,但这个答案似乎不成比例地强调了那些25秒的重要性,因此似乎偏向于“依赖客户”。这是不明智的,期间。特别是如果总计100万个刀片的成本可以忽略不计,即25秒。您永远不确定所有客户是否都能正确实施所有必需的检查,即使您知道当前存在的客户,即使这样,您也不知道将来的任何其他客户。
您必须考虑的是当您的数据由于数据库系统未强制执行的某些约束而“损坏”时将产生的修复成本。例如,思考如果必须解决以下问题(Find GUID in database)的“穷人”将在25秒内完成。
如果执行所有约束检查所需的总时间使您的事务显着变慢,那么即使这样,尝试说服您的组织投资更多或更快的硬件也是更明智的
保证满足诚信规则的数据是当今大多数企业中最重要的资产,应该如此珍惜。
答案 4 :(得分:0)
信任是好的,控制更好。
通常你根本不需要reg exps。请参阅此处以获取示例:Regular Expressions _# at end of string。 Substr,translate,instr ...功能强大且速度快。
答案 5 :(得分:0)
速度的差异在很大程度上取决于您的硬件 - 更快的处理器,内存,磁盘,甚至数据库释放都会影响约束/无约束时间比。 我看到不同硬件组合的数字(明智的百分比)有很大差异。 因此,正确的答案是使用和不使用constaraints测试您的特定实现,并将经验与帮助台支持的成本或数据清理进行比较以修复“错误数据”,或两者兼而有之。
如果您曾经负责从数据库迁移数据,其中所有约束都是“在客户端实现的”,那么您很快就会成为服务器上可行的constorints实现中的真正beliver。
如果相信您只使用一个使用您的数据的应用程序并且所有应用程序将使用相同的“约束”,那将是非常危险的。但即使在这种情况下,不同的开发人员也有不同的知识,并且随着应用程序的老化以及新的开发人员的流动,新的开发人员可能对在多年代码开发中隐藏的一些约束一无所知。
换句话说,当设计思考“为什么我们不需要这种约束”而不是“为什么我们需要它”时,测试就是王者。
答案 6 :(得分:-1)
这实际上取决于您的整体架构。如果您的数据库被严格用作数据存储,则不应该对数据库进行检查。
您提出这个问题的事实表明您以更传统的方式使用数据库。在这种情况下,通常最好在数据库上添加尽可能多的约束,然后分析以查看需要删除哪些约束以提高性能(此时您需要确定性能提升是否值得降低安全性)。
答案 7 :(得分:-1)
我真正的问题是,数据是否可以从应用程序以外的来源输入数据库?是否会从其他应用程序或查询窗口运行大型导入或查询。如果您有一个新客户想要从以前的供应商导入记录,那么如何处理?如果您可以设想opf为何可以从应用程序外部更改数据并且必须对所有数据强制执行规则,那么您需要检查约束或触发器来强制执行该操作。其他应用程序的工作方式有多重要?例如,如果您将所有电话号码存储为仅数字并在显示数据的页面上添加格式,如果有人在您显示的信息中添加电话号码(111)111-1111,会产生什么影响。数据完整性是数据库的关键部分。如果您不能依赖于正确格式的数据或遵循正确的规则(例如,字段只有三个正确的值)那么您的dqata就变得不那么有价值了。根据严重程度,它可能是一个严重的失败。
另一件需要考虑的事情是,您是否有能够直接访问非管理员表的人?如果是这样,在数据库级别强制执行的规则可以帮助减少欺诈的可能性。 (开发人员经常忘记保护授权用户的数据。我在这里讨论的规则更可能通过触发器强制执行,而不是简单的检查约束,除非可能是收费的最高限制,但在设计数据库时需要考虑)