none
对唯一索引键检索出现死锁,没辙了。 RRS feed

  • 问题

  • hi,

    有一个表,不到30万笔记录,主键(聚集)是自增字段ID,还有一个唯一索引12位字符字段NO,查询语句是 select * from Table where NO = @NO,多用户时候大量的报死锁。

    这个有点想不通,这种对唯一索引的检索应该是很高效的,怎么会死锁了。程序是Web程序,客户端访问才200多个Session。

    请问还能怎么改进呢?

    谢谢。

     

     


    学习无涯,游戏与白开水作伴。
    2011年1月24日 3:22

答案

  • SQL什么版本,有没禁用自动更新统计,是否从旧版升级过来。。。 按道理来说,30万记录,随便找台PC也能应付200台客户端使用
    Try SQL Server 2008 QQ:315054403 dgdba@hotmail.com
    2011年1月24日 9:39
  • Not good practice in general, sql may use wrong plan when change search value. 
    2011年1月31日 4:19

全部回复

  • Did you check execution plan to make sure sql uses that index?
    2011年1月24日 3:28
  • Read processes shouldn't lock each other because they use shared lock only, you can enable deadlock trace flag to find details.
    2011年1月24日 3:57
  • 如果所有的客户端访问都是读的话,是不应该有死锁的。

    不过你的select *语句用到了两个索引,第一个是通过唯一索引找到聚集键,第二个是通过聚集键在聚集索引中读取全部数据。这就有可能和其他的update语句造成死锁。 具体可以参考SQL server 2005技术内幕: T-SQL programming一书中的事物和锁那一章。

    2011年1月24日 4:54
  • 谢谢各位。

    to miao:

    我是一查询计划的时候,很奇怪的事情:同一个SQL语句,有时候提示我对NO字段创建一个非聚集索引;有时候又没有提示。

    to chengyon:

    客户端不会仅仅只有select的,但是update的非常少。就算是select,有时候也会发生超时。

     

    所以,我有个想法:把NO字段改为聚集索引,ID字段由原来的聚集的主键改为非聚集的主键。我不确定这种做法是否有效。


    学习无涯,游戏与白开水作伴。
    2011年1月24日 5:30
  • SQL什么版本,有没禁用自动更新统计,是否从旧版升级过来。。。 按道理来说,30万记录,随便找台PC也能应付200台客户端使用
    Try SQL Server 2008 QQ:315054403 dgdba@hotmail.com
    2011年1月24日 9:39
  • 谢谢各位。

    to miao:

    我是一查询计划的时候,很奇怪的事情:同一个SQL语句,有时候提示我对NO字段创建一个非聚集索引;有时候又没有提示。

    to chengyon:

    客户端不会仅仅只有select的,但是update的非常少。就算是select,有时候也会发生超时。

     

    所以,我有个想法:把NO字段改为聚集索引,ID字段由原来的聚集的主键改为非聚集的主键。我不确定这种做法是否有效。


    学习无涯,游戏与白开水作伴。
    Depends on number of rows involved, optimizer may use index differently.
    2011年1月24日 15:03
  •  

    没有禁用“禁用自动更新统计”,数据库倒是从旧版本2000升级到2005的。

    “Depends on number of rows involved, optimizer may use index differently.” 这个理论我倒还不懂,不清楚数据库选择索引和数字列有什么关系。

     

     

     

     

     


    学习无涯,游戏与白开水作伴。
    2011年1月26日 2:49
  • Take your query as example, say set @no = 1. If table has 1000 rows but only couple of them have value 1 in NO column, optimizer will seek index on NO column to get results. If 500 rows have value 1 in NO column, optimizer will scan clustered index to get results because it costs less than seek index on NO column. 
    2011年1月26日 3:35
  • 呵呵,NO是唯一索引,肯定不可能一个列存在多个值的。

    但是有一点让我担心,NO字段允许空,但实际情况是表中此字段没有null值。

    此表主键是ID,NO是唯一索引,还有两个多字段索引和NO有关。实际的查找语句形如:select * from Table where NO=@NO

    这个SQL查询常常超时。

     


    学习无涯,游戏与白开水作伴。
    2011年1月28日 8:48
  • I was talking about general situation. With unique index, the column can only have one row with null value. Regarding timeout, check executuion plan to make sure optimizer uses index on NO column and check server processes to find out if there's blocking.
    2011年1月28日 14:27
  • 谢谢rmiao。

    我找到一个方法,在SQL语句中指定索引。

    select * from Table with(index(Index_NO)) where no = '123456'

    目前测试,使用查询计划,没有出现过推荐建索引了。但这个还需要实践一下。

     

     

     


    学习无涯,游戏与白开水作伴。
    2011年1月31日 2:57
  • Not good practice in general, sql may use wrong plan when change search value. 
    2011年1月31日 4:19
  • 是的,我觉得还是需要把SQL语句修改为参数形式的:

    select * from Table with(index(Index_NO)) where no = @NO

    谢谢你。

     

     


    学习无涯,游戏与白开水作伴。
    2011年2月5日 1:42
  • 如何Excute Plan无法使用到所建索引,那么就使用显式索引吧,

    使用With Index关键字,显式指明好了

     

    2011年3月3日 6:52