【问题标题】:SQL Server unique index on nvarchar issue关于 nvarchar 问题的 SQL Server 唯一索引
【发布时间】:2014-06-18 12:08:51
【问题描述】:

我有一个带有 nvarchar(50) 列的 SQL Server 表。此列必须是唯一的,不能是 PK,因为另一列是 PK。所以我在这个列上设置了一个非聚集唯一索引。

在可序列化事务中的大量插入语句期间,我只想在不同的事务中执行基于此列的选择查询。但是这些插入似乎锁定了表。例如,如果我将唯一列的数据类型更改为 bigint,则不会发生锁定。

为什么 nvarchar 不工作,而 bigint 工作?使用 nvarchar(50) 作为数据类型,我怎样才能达到同样的效果?

【问题讨论】:

  • 你不能只给这个列添加一个唯一的约束和索引吗?桌子有多大?
  • 我不确定为什么会发生阻塞。但是,您可以将值放在另一个表中并只使用外键引用吗?
  • 我忘了说我在 nvarchar(50) 列上有一个唯一索引,我将编辑我的问题
  • 另一个表有什么帮助,因为我仍然需要对该表进行插入和选择?
  • 您的SELECT 需要什么样的隔离?您想要未提交的行吗?或者是否可以将它们包含在您的结果中?

标签: sql sql-server nvarchar unique-index


【解决方案1】:

毕竟,谜团解开了!我猜这是相当愚蠢的情况..

问题出在 select 语句中。 where 子句缺少引号,但由于现有数据只是数字的巧合,因此选择没有失败,只是在插入提交之前没有执行。插入第一个字母数字数据时,选择语句开始失败,并出现“将数据类型 nvarchar 转换为数字时出错”

例如 而不是

SELECT [my_nvarchar_column]  
FROM [dbo].[my_table]  
WHERE [my_nvarchar_column] = '12345'

选择语句是

SELECT [my_nvarchar_column]  
FROM [dbo].[my_table]  
WHERE [my_nvarchar_column] = 12345

我猜是执行了静默强制转换,没有使用唯一索引导致阻塞。 修复了该语句,现在一切正常。

感谢大家的帮助,对于这个相当愚蠢的问题,我们深表歉意!

【讨论】:

    【解决方案2】:

    首先,您可以将 PK 更改为非聚集索引,然后您可以在该字段上创建聚集索引。当然,根据您的使用情况,这可能是个坏主意,或者根本没有帮助。

    您可能有一个覆盖索引的用例,请参阅前面的question re: covering index

    您可以通过更改这些查询的隔离级别将“其他查询”更改为非阻塞。

    在单个事务中插入大量行的必要性相对不常见。您可能能够简单地不使用事务,或者将事务拆分为较小的事务集以避免锁定表的大部分。例如,您可以在事务中将记录插入待处理表(在正常活动中不使用),然后如果不需要实时发布到主表,则将这些记录在较小的事务中迁移到主表。

    添加

    也许是最明显的问题。您确定必须使用可序列化事务来插入大量记录吗?这些在金融交易之外相对很少需要,并且与其他隔离级别相比会产生高并发成本?

    添加

    根据您对“全部或全部”的评论,您描述的是原子性,而不是可序列化性。即,您可以为大型插入事务使用不同的隔离级别,并且仍然获得原子性。

    第二件事,我注意到您指定了大量的插入语句。这听起来就像您应该能够将这些插入推送到挂起/暂存表中,然后从暂存表执行单个插入或批量插入到生产表中。是的,这需要更多的工作,但您可能只是有一个需要额外努力的现有问题。

    【讨论】:

    • 将索引更改为聚集索引,将 PK 更改为非聚集索引,结果相同。根据这个栏目我还是选不出来。
    • 是的,一个可序列化的事务是必要的。那些大的插入是不常见的,但在此期间表必须是可访问的。没有下班时间可以进行插入。插入必须全部失败或成功。我想我可以使用一个挂起的表,但我也应该将数据维护到这个表中(例如在删除之后),否则唯一约束将没有结果。但这似乎是一个很大的努力。
    • 嗯,这不仅仅是原子性,因为如果插入失败,则必须对先前在同一事务中处理的其他数据进行回滚。我将尝试挂起表解决方案,作为最后但更安全的选择,即使我想我应该在两个表之间保持相同的数据,并小批量插入新行。感谢您的建议。
    【解决方案3】:

    您可能希望在查询中添加 NOLOCK 提示(也称为 READUNCOMMITTED)。它将允许对已插入的数据执行“脏读”。

    例如

    SELECT [my_nvarchar_column] FROM [dbo].[locked_table] WITH (NOLOCK)

    在这里看看更好的解释:

    http://www.mssqltips.com/sqlservertip/2470/understanding-the-sql-server-nolock-hint/

    还有这里的 READUNCOMMITTED 部分:

    http://technet.microsoft.com/en-us/library/ms187373.aspx

    【讨论】:

    • OP 专门插入SERIALIZABLE 事务,所以我会有点犹豫是否提供基本上无视事务的东西(即,行可能会消失)。我们可能需要来自 OP 的更多信息...
    • 要求可序列化的事务。
    猜你喜欢
    • 1970-01-01
    • 2014-03-04
    • 1970-01-01
    • 2010-11-29
    • 1970-01-01
    • 2018-05-22
    • 2017-09-22
    • 2012-05-03
    相关资源
    最近更新 更多