2013-10-23 71 views
2

我正在使用一个asp.net MVC4项目并使用SQL Server 2008.我的数据库表包含100000行。此外,连接字符串属性的最大池大小设置为1000000,并将池设置为true。Sql timeout虽然最大池大小设置为1000000,但异常

我的表结构如下:

CREATE TABLE tblNews 
(
ID int IDENTITY(1,1) NOT NULL, 
Url nvarchar(300) UNIQUE NOT NULL, 
PubDate datetime NOT NULL, 
Active bit NOT NULL, 
Hit int NOT NULL, 
... 
) 

和如下有一个指标:

CREATE NONCLUSTERED INDEX indexTblNews_Url 
ON tblNews(Url) 

我选择的查询是:

CREATE PROC spNewsGet 
    @Url nvarchar(300) 
AS 
    UPDATE tblNews 
    SET Hit = Hit + 1 
    WHERE Url = @Url 
    AND PubDate > GETDATE() 
    AND Active = 1; 

    SELECT 
     * 
    FROM tblNews 
    WHERE Url = @Url 
    AND PubDate > GETDATE() 
    AND Active = 1 
    ORDER BY PubDate DESC 

在低评价的站点有没有问题,这完美的作品。但是在数据库大到100000行和网站有200万个单用户/日的情况下,它会崩溃。它在三个页面之一抛出SqlTimeout异常。当我点击一个页面时,几乎所有的页面都会给出上述例外。

我检查了硬件性能和处理器消耗在I7 3.6 GHZ的%70,RAM的消耗是1.5 GB。但是有更多空的内存。我怎样才能克服这个问题?

任何帮助将不胜感激。

+1

您确定在使用它们后关闭了连接吗?你有没有在SQL服务器中检查你的执行计划,看看你是否正确使用你的索引? – Paddy

+0

那么,你正在通过PubDate搜索和订购,为什么不索引呢?另外,我猜'url'不是一个独特的列? – MikeSmithDev

+0

@ Paddy我关闭了所有的连接,我也检查了.net分析器。没有开放的连接。 – Mesut

回答

1

很有可能您使用的是SqlConnection。尝试将连接的ConnectionTimeout属性设置为0以指示无限超时。如果您未使用SqlConnection,则可能会设置类似的属性。

+0

这不是正确的解决方案,我的期望是数据库得到快速。 – Mesut

+1

@Mesut因为你没有在你的问题中指定这个,我怀疑你想要一个快速和肮脏的解决方案来解决这个问题。我很高兴听到您明白这是一种解决方法,而不是真正的解决方法。我投了你的问题,所以希望有人能帮助你。 –

1

对于某些网站而非其他网站而言,快速工作的一个可能原因是,对于大量网站,该网址对于现有索引无法有效选择。因此,UPDATE可能会升级超出行锁,导致争用聚集/非聚集索引。

我怀疑连接不足是一个问题 - 设置connection pool max size超过32k为pointless,并发SQL连接也将取决于与.Net threads有关的因素。

我真的不明白为什么PubDate是将来日期,但如果PubDate > GETDATE(),和/或Active = 1显著减少记录的数量,在更新查询,然后我还要补充这些领域的一个或两个索引(如果适用),即:

CREATE NONCLUSTERED INDEX indexTblNews_Url 
ON tblNews(Url, PubDate); 

您也在复制查询 - 一次更新,一次选择。您可以通过临时表减少冗余并重新加入。

CREATE PROC spNewsGet 
@Url nvarchar(300) 
AS 
    SELECT ID 
    INTO #tmp 
    FROM tblNews 
    WHERE Url = @Url 
    AND PubDate > GETDATE() 
    AND Active = 1; 

    UPDATE tblNews 
    SET Hit = Hit + 1 
    FROM tblNews INNER JOIN #tmp on #tmp.ID = tblNews.ID; 

    -- Consider also using SET TRANSACTION ISOLATION SNAPSHOT or READ UNCOMMITTED here. 
    SELECT tblNews.* 
    FROM tblNews INNER JOIN #tmp on #tmp.ID = tblNews.ID 
    ORDER BY PubDate DESC; 
GO 

最后,按照注释,你可以考虑删除对最终选择的隔离级别,提供结果集不用于“交易的关键”的用法。

+1

他可能只是使用变量而不是tmp表,因为它只是一个ID。 – MikeSmithDev

+1

使用#TempTable消耗更多的性能。我必须使用一个变量。但是在选择结果处有smore列。我怎样才能选择并设置一个表格并获得所有结果列? – Mesut

+0

最后,根据评论,您可以考虑在最终选择中删除隔离级别,前提是结果集不用于'transaction critical'用法。 我该怎么做? – Mesut