C# executescalar 在大 table 上真的很慢

C# executescalar realy slow on big table

我有一个问题,executescalar 在 table 上有超过 200.000 条记录时真的很慢。

我使用的方法检查 table 中是否存在 varchar 和 returns 计数以查看是否可以找到任何内容:

public static bool AlreadyQueued(string url)
{
    using (SqlConnection connection = new SqlConnection(_connectionString))
    {
        SqlCommand cmd = new SqlCommand("SELECT Count(queueID) from PriorityQueue where absolute_url = @url")
        {
            Connection = connection,
            CommandType = CommandType.Text
        };
        cmd.Parameters.AddWithValue("@url", url);
        connection.Open();
        var count = (int)cmd.ExecuteScalar();
        return count > 0;
    }
}

我的 table 是这样构建的:

CREATE TABLE PriorityQueue
(
    queueID int IDENTITY(1,1) PRIMARY KEY,
    absolute_url varchar (900),
    depth int,
    priorty int
);

有什么方法可以使我的 C# 方法更快,或者我是否需要更改 table 中的某些内容?

ExecuteScalar() 仅用于 运行 您的查询,您获取的数据更多,这需要更多时间。

您尝试过 "SELECT TOP 1 queueID from PriorityQueue where absolute_url = @url" 吗?应该会有明显的性能提升。

无论如何,我建议您将存储过程添加到您的数据库以return您想要的布尔值

Create PROCEDURE UrlFound @absolute_url varchar(900)  
AS  
IF (EXISTS(SELECT TOP 1 1 from PriorityQueue where absolute_url = @absolute_url))
    RETURN 1  
ELSE  
   RETURN 0;  
GO  

然后你可以这样测试它:

DECLARE @result bit
exec @result = UrlFound 'YourAbsoluteUrl'
print @result 

SQL 大量记录计数总是很慢。请寻找其他选择。您可以根据需要使用 if Exists 或任何其他选项。

下面是一些可以帮助您理解它的链接。

SQL Server Count is slow

SQL count(*) performance

SQL Server - Speed up count on large table

正如其他人已经指出的那样,缓慢是在数据库中。由于您实际上并不需要确切的计数,而是一个指示行是否存在的布尔值,因此您可能会像这样获得轻微的性能提升:

SELECT TOP 1 1 from PriorityQueue where absolute_url = @url

使用此查询,一旦找到第一个(并且可能是唯一的)匹配项,数据库就可以停止搜索。

但要获得显着的性能提升,您需要向 absolute_url 列添加索引。但是该列当前定义为 varchar(900) ,它(如果我用谷歌搜索正确的话)就在索引中列的长度限制。如果你这样索引它,索引将占用与 table 本身相同数量的 space。

因此,如果可能,请缩短该列,然后在其上添加索引。如果您绝对不能缩短它,您可以再添加一个包含列的前(比如)50 个字符的列,然后索引该列。那么你可以这样做:

SELECT TOP 1 1 from PriorityQueue where absolute_url = @url and shortened_url = @shortenedUrl

然后您还需要添加 @shortenedUrl 参数,该参数(当然)应该包含您要查找的 url 的前 50 个字符。

20,000 行的选择总是会稍微慢一些,检查您的索引并可能在后台工作程序中执行 AlreadyQueued 可能是个好主意。

https://msdn.microsoft.com/en-us/library/system.componentmodel.backgroundworker(v=vs.110).aspx