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
我有一个问题,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