简体   繁体   English

SQL Server在读取带有外键的列时遇到问题

[英]SQL Server problems reading columns with a foreign key

I have a weird situation, where simple queries seem to never finish 我有一个奇怪的情况,简单的查询似乎永远无法完成

for instance 例如

SELECT top 100 ArticleID FROM Article WHERE  ProductGroupID=379114

returns immediately 立即返回

SELECT top 1000 ArticleID FROM Article WHERE  ProductGroupID=379114

never returns 永不归来

SELECT ArticleID FROM Article WHERE  ProductGroupID=379114

never returns 永不归来

SELECT top 1000 ArticleID FROM Article

returns immediately 立即返回

By 'returning' I mean 'in query analyzer the green check mark appears and it says "Query executed successfully"'. “返回”是指“在查询分析器中,绿色复选标记出现,并显示“查询已成功执行””。

I sometimes get the rows painted to the grid in qa, but still the query goes on waiting for my client to time out - 'sometimes': 有时我会在qa中将行绘制到网格上,但是查询仍然继续等待客户端超时-有时:

SELECT     
   ProductGroupID AS Product23_1_, 
   ArticleID AS ArticleID1_, 
   ArticleID AS ArticleID18_0_, 
   Inventory_Name AS Inventory3_18_0_, 
   Inventory_UnitOfMeasure AS Inventory4_18_0_, 
   BusinessKey AS Business5_18_0_, 
   Name AS Name18_0_, 
   ServesPeople AS ServesPe7_18_0_, 
   InStock AS InStock18_0_, 
   Description AS Descript9_18_0_, 
   Description2 AS Descrip10_18_0_, 
   TechnicalData AS Technic11_18_0_, 
   IsDiscontinued AS IsDisco12_18_0_, 
   Release AS Release18_0_, 
   Classifications AS Classif14_18_0_, 
   DistributorName AS Distrib15_18_0_, 
   DistributorProductCode AS Distrib16_18_0_, 
   Options AS Options18_0_, 
   IsPromoted AS IsPromoted18_0_, 
   IsBulkyFreight AS IsBulky19_18_0_, 
   IsBackOrderOnly AS IsBackO20_18_0_, 
   Price AS Price18_0_, 
   Weight AS Weight18_0_, 
   ProductGroupID AS Product23_18_0_, 
   ConversationID AS Convers24_18_0_, 
   DistributorID AS Distrib25_18_0_, 
   type AS Type18_0_
FROM         
   Article AS articles0_
WHERE     
   (IsDiscontinued = '0') AND (ProductGroupID = 379121)

shows this behavior. 显示此行为。

I have no idea what is going on. 我不知道发生了什么。 Probably select is broken ;) 可能是选择被打破;)

I got a foreign key on ProductGroups 我在ProductGroups上有外键

ALTER TABLE [dbo].[Article] WITH CHECK ADD CONSTRAINT [FK_ProductGroup_Articles] 
FOREIGN KEY([ProductGroupID]) 
REFERENCES [dbo].[ProductGroup] ([ProductGroupID]) 
GO 
ALTER TABLE [dbo].[Article] CHECK CONSTRAINT [FK_ProductGroup_Articles] 

there are some 6000 rows and IsDiscontinued is a bit, not null, but leaving this condition out does not change the outcome. 有大约6000行,IsDiscontinued有点,不为null,但是不保留此条件不会改变结果。

Anyone can tell me how to handle such a situation? 有人可以告诉我如何处理这种情况吗? More info, anyone? 更多信息,有人吗?

Additional Info: this does not seem to be restricted to this Foreign Key, but all/some referencing this entity. 附加信息:这似乎并不限于此外键,而是所有/某些引用此实体的对象。

A few things that I would try out, to try and help diagnose the problem (may just rule things out): 我将尝试尝试并帮助诊断问题的一些方法(可能只是排除某些情况):

Temporarily try the query that doesn't ever return with either a NOLOCK or READPAST table hint ie 临时尝试不返回NOLOCK或READPAST表提示的查询,即

SELECT top 1000 ArticleID FROM Article WITH (NOLOCK) WHERE ProductGroupID=379114

Does that return the results or not? 那是否返回结果? Maybe if there's a row or data page locked somewhere (by some process that for some reason has a long-running lock), the query is being held up by it which this could show up as being the case. 也许如果某行或数据页被锁定在某处(由于某种原因,由于某种原因该进程具有长时间运行的锁定),查询就会被它阻止,这种情况可能会出现。

Also, execute your problem query (WITHOUT the table hint) in one SSMS window, and note your SPID (the number in brackets in the bottom bar, alongside your login account) . 另外,在一个SSMS窗口中执行问题查询(没有表提示),并记下您的SPID(底部栏括号中的数字,以及您的登录帐户)。 In a separate window, run the following a few times repeatedly, and see what it shows: 在一个单独的窗口中,重复运行以下几次,然后查看显示的内容:

SELECT status, wait_type
FROM sys.dm_exec_requests
WHERE session_id = <YourQuerySPID>

There's a good reference here on what the different wait types mean, and this could flag up the fact the query is waiting on something. 关于不同的等待类型的含义, 这里很好的参考 ,这可以表明查询正在等待某种事实。

Update: 更新:
See this SO question on how to find blocked/blocking processes - I don't want to steal votes away from the answers in there! 看到这个关于如何查找被阻止/阻止过程的问题 -我不想从那里的答案中窃取票!

  • Do you have an index on the column ProductGroupID? 在ProductGroupID列上有索引吗? If so are your indexes fragmented? 如果是这样,您的索引是否零散?
  • Are your statistics up to date? 您的统计信息是最新的吗?
  • Have you reviewed the Query Plans produced? 您是否查看了生成的查询计划? Are they the same? 他们是一样的吗?

When you are performance tuning a query you should strive to ensure that you are comparing like for like, that is that each query is retrieving the result set from disk and not the buffer cache. 当您对查询进行性能优化时,您应努力确保您进行的“按赞”比较,即每个查询都从磁盘而不是从缓冲区高速缓存中检索结果集。

You can clear the buffer cache using the command DBCC DROPCLEANBUFFERS however this is NOT often an option for a production database. 您可以使用命令DBCC DROPCLEANBUFFERS清除缓冲区高速缓存,但是对于生产数据库来说,这通常不是一个选项。

You will also want to ensure that the statistics are up to date for the columns that form part of your WHERE clause predicates. 您还将要确保构成WHERE子句谓词一部分的列的统计信息是最新的。 This will ensure that SQL Server determines the most optimal query plan to use based on the selectivity of your data. 这将确保SQL Server根据数据的选择性确定要使用的最佳查询计划。

Couple things - others have already pointed in those directions: 几件事情-其他人已经指出了这些方向:

  • do you have an index on your foreign key?? 您的外键上有索引吗?

     CONSTRAINT [FK_ProductGroup_Articles] FOREIGN KEY([ProductGroupID]) REFERENCES [dbo].[ProductGroup] ([ProductGroupID]) 

    Creating a foreign key does not automatically create an index on that foreign key column - contrary to popular belief. 与流行的看法相反,创建外键并不会自动在该外键列上创建索引。

    If not - it would definitely help to index ProductGroupID - either separately or in a compound index. 如果不是这样的话-单独或在复合索引中对ProductGroupID进行索引肯定会有所帮助。

  • have you ever re-create and updated your statistics? 您是否曾经重新创建和更新过统计信息? Have you recently inserted a great amount of data? 您最近是否插入了大量数据?

    Simply run this command on those tables involved in your queries: 只需在查询所涉及的那些表上运行此命令:

     UPDATE STATISTICS (table name) 
  • minor issue: if you compare against a BIT column, I would personally use 次要问题:如果将您与BIT列进行比较,我个人会使用

     (IsDiscontinued = 0) 

    There's no benefit in putting that 0 into single quotes and thus making it a string - SQL Server just has to convert it back to a BIT.... 将0放在单引号中并使其成为字符串没有好处-SQL Server只需将其转换回BIT。

Foreign keys only define the relationship/constraint, you still need an index if you will want to find these values fast, so try this: 外键仅定义关系/约束,如果您想快速找到这些值,则仍需要索引,因此请尝试以下操作:

CREATE NONCLUSTERED INDEX IX_Article_ProductGroupID ON dbo.Article 
    (
    ProductGroupID 
    ) INCLUDE (IsDiscontinued) WITH( STATISTICS_NORECOMPUTE = OFF, IGNORE_DUP_KEY = OFF, ALLOW_ROW_LOCKS = ON, ALLOW_PAGE_LOCKS = ON) 
 ON [PRIMARY]
GO

it adds an index on Article.ProductGroupID and covers Article.IsDiscontinued 它在Article.ProductGroupID上添加索引,并覆盖Article.IsDiscontinued

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM