我遇到的问题是,在具有超过200,000条记录的表格上,执行标记真的很慢。
我使用的方法检查表中是否存在varchar并返回计数以查看是否可以找到任何内容:
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;
}
}
我的表格是这样构建的:
CREATE TABLE PriorityQueue
(
queueID int IDENTITY(1,1) PRIMARY KEY,
absolute_url varchar (900),
depth int,
priorty int
);
有什么方法可以让我的C#方法更快,还是我需要更改表格中的内容?
答案 0 :(得分:1)
数据库中的缓慢,正如其他人已经指出的那样。由于您实际上并不需要精确计数,而是指示行是否存在的布尔值,因此可能会略微提高性能:
SELECT TOP 1 1 from PriorityQueue where absolute_url = @url
使用此查询,数据库可以在找到第一个(也可能是唯一的)匹配后停止搜索。
但要获得显着的性能提升,您需要在absolute_url
列中添加索引。但是该列目前被定义为varchar(900)
,这是(如果我已经正确搜索),在列可以在索引中的时间限制。如果对其进行索引,索引将占用与表本身大致相同的空间量。
如果可能,请缩短列,然后在其上添加索引。如果你绝对不能缩短它,你可以添加一个包含列的第一个(例如)50个字符的列,然后将该列编入索引。然后你可以这样做:
SELECT TOP 1 1 from PriorityQueue where absolute_url = @url and shortened_url = @shortenedUrl
然后你还需要添加@shortenedUrl
参数,该参数应该(当然)包含你要查找的网址的前50个字符。
答案 1 :(得分:0)
ExecuteScalar()仅用于运行查询,提取数据的时间更长,需要花费更多时间。
答案 2 :(得分:0)
您是否尝试过"SELECT TOP 1 queueID from PriorityQueue where absolute_url = @url"
?应该会有明显的性能提升。
在任何情况下,我建议您向数据库添加一个存储过程以返回所需的布尔值
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
答案 3 :(得分:0)
SQL Count总是很慢,有大量记录。请寻找其他选择。您可以根据您的要求使用“存在”或任何其他选项。
以下是一些可以帮助您理解的链接。
答案 4 :(得分:0)
20,000行选择总是稍微慢一点,查看索引并在后台工作程序中执行AlreadyQueued
可能是个好主意。
https://msdn.microsoft.com/en-us/library/system.componentmodel.backgroundworker(v=vs.110).aspx