c# - SQL Server 存储过程的性能问题

标签 c# sql sql-server stored-procedures performance

我使用 ANTS 探查器来确定我的 C# 应用程序中剩余的瓶颈:SQL Server 存储过程。我正在使用 SQL Server 2008。这里的任何人都可以帮助我提高性能,或者指导我如何做才能让它变得更好或性能更高吗?

首先,这是程序:

PROCEDURE [dbo].[readerSimilarity] 
-- Add the parameters for the stored procedure here
@id int,
@type int
AS
BEGIN
-- SET NOCOUNT ON added to prevent extra result sets from
-- interfering with SELECT statements.
SET NOCOUNT ON;

-- Insert statements for procedure here
IF (@type=1) --by Article
    SELECT id1, id2, similarity_byArticle FROM similarity WHERE (id1 = @id OR id2 = @id) 
AND similarity_byArticle != 0

ELSE IF (@type=2) --by Parent
    SELECT id1, id2, similarity_byParent FROM similarity WHERE (id1 = @id OR id2 = @id) 
AND similarity_byParent != 0

ELSE IF (@type=3) --by Child
    SELECT id1, id2, similarity_byChild FROM similarity WHERE (id1 = @id OR id2 = @id) 
AND similarity_byChild != 0

ELSE IF (@type=4) --combined
    SELECT id1, id2, similarity_combined FROM similarity WHERE (id1 = @id OR id2 = @id) 
AND similarity_combined != 0

END

表格' similarity ' 由两个 id 组成s ( id1id2 )和一些存储 double 的列值。约束是 id1 < id2 .

Column     Data
-----      ----
ID1         PK, Indexed
ID2         PK, Indexed

The table contains 28.5 million entries.

Stored Procedure Background

The job of the stored procedure is to get all the rows that have the parameter id in either id1 or id2. Additionally, the column specified by the type-parameter cannot be zero.

The stored procedure is called multiple times for different ids. Although only taking ~1.6 ms per call, it sums up, when calling it 17,000 times.

The processor is running at only 25%, which seems to be because the application is waiting for the procedure call to return.

Do you see any way to speed things up?

Calling the Stored Procedure C# Code Snippet

private HashSet<NodeClustering> AddNeighbourNodes(int id)
    {
        HashSet<NodeClustering> resultSet = new HashSet<NodeClustering>();
        HashSet<nodeConnection> simSet = _graphDataLoader.LoadEdgesOfNode(id);

        foreach (nodeConnection s in simSet)
        {
            int connectedId = s.id1;
            if (connectedId == id)
                connectedId = s.id2;

            // if the corresponding node doesn't exist yet, add it to the graph
            if (!_setNodes.ContainsKey(connectedId))
            {
                NodeClustering nodeToAdd = CreateNode(connectedId);
                GraphAddOuter(nodeToAdd);
                ChangeWeightIntoCluster(nodeToAdd.id, s.weight);
                _bFlowOuter += s.weight;
                resultSet.Add(nodeToAdd);
            }
        }

        // the nodes in the result set have been added 
                   to the outernodes -> add to the outernodes count
        _setNodes[id].countEdges2Outside += resultSet.Count;

        return resultSet;
    }

C# 代码背景信息

每次新的 id 时都会调用此方法被添加到集群中。它获取该 id 的所有连接节点(当数据库中有 id1=idid2=id 条目时,它们已连接)通过

_graphDataLoader.LoadEdgesOfNode(id);

然后它检查所有连接的 ids如果它们还没有加载:

if (!_setNodes.ContainsKey(connectedId))

它加载它们:

CreateNode(connectedId); 

方法:

_graphDataLoader.LoadEdgesOfNode(id); 

再次被调用,这次是 connectedId .

我需要它来获取新节点与集合中已有节点的所有连接。

我可能会收集 ids在所有节点中,我只需要使用 ID 列表添加和调用我的存储过程一次。

想法

我可能可以通过类似的方式立即加载已连接的 ids 连接

        SELECT id1, id2, similarity_byArticle FROM similarity WHERE 
                   (id1 = @id OR id2 = @id OR
        id1 IN (SELECT id1 FROM similarity WHERE id2 = @id) OR 
        id2 IN (SELECT id1 FROM similarity WHERE id2 = @id) OR
        id1 IN (SELECT id2 FROM similarity WHERE id1 = @id) OR 
        id2 IN (SELECT id2 FROM similarity WHERE id1 = @id))
                    AND similarity_byArticle != 0

但随后我会得到比我需要的更多的条目,因为我也会为已经加载的节点获取它们(根据我的测试,这些条目将占调用的 75% 左右)。

问题

  1. 如何加快存储过程的速度?
  2. 我可以采用不同的方式吗?有没有更高效的方法?
  3. 我可以使用 List<int> 吗?作为 SP 参数?
  4. 还有其他想法吗?

最佳答案

如果它运行得那么快,您的问题可能出在对过程的重复调用的绝对数量上。有没有一种方法可以修改存储过程和代码以在一次调用中返回应用程序所需的所有结果?

优化运行时间少于 2 毫秒的查询可能不是一项富有成效的工作。我怀疑您能否通过查询调整缩短超过一毫秒的时间。

关于c# - SQL Server 存储过程的性能问题,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/1444426/

相关文章:

c# - smtp - 每封邮件都有超时

c# - LINQ 总和数据表列,其中

mysql - 如何支持用户为我的业务逻辑处理定义规则?

c# - 如何从YouTube观看记录中获取最新视频

c# - 具有透明背景的重叠 PicuresBox

sql - 基于不同列的值的默认列值

c# - SQL 语法错误(INSERT 命令)

sql-server - 将所有 SSRS 报告的共享数据源路径更新为不同的路径

SQL Server 2008 - 仅更新表中特定数量的行

sql-server - 如何回滚存储过程中的事务?