SQL Server存储过程的性能问题

Aag*_*nor 1 c# sql sql-server performance stored-procedures

我使用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
Run Code Online (Sandbox Code Playgroud)

表' similarity'由两个ids(id1id2)和一些存储double值的列组成.约束是这样的id1 < id2.

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

The table contains 28.5 million entries.

存储过程背景

存储过程的工作是让所有具有参数的行id任一id1id2.此外,type-parameter指定的列不能为零.

对于不同的存储过程被多次调用ids.虽然只~1.6 ms接听每次通话,但总结起来,称它为17,000次.

处理器只运行25%,这似乎是因为应用程序正在等待程序调用返回.

你有没有办法加快速度?

调用存储过程 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;
    }
Run Code Online (Sandbox Code Playgroud)

C#代码背景信息

每次将新id添加到群集时都会调用此方法.它获取所有连接的节点id(它们是连接的,当数据库中带有id1=id或带有条目时id2=id)

_graphDataLoader.LoadEdgesOfNode(id);
Run Code Online (Sandbox Code Playgroud)

然后它会检查所有已连接的ids以及它们是否尚未加载:

if (!_setNodes.ContainsKey(connectedId))
Run Code Online (Sandbox Code Playgroud)

它载入它们:

CreateNode(connectedId); 
Run Code Online (Sandbox Code Playgroud)

方法:

_graphDataLoader.LoadEdgesOfNode(id); 
Run Code Online (Sandbox Code Playgroud)

再次被召唤,这一次与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
Run Code Online (Sandbox Code Playgroud)

但是后来我会得到比我需要的更多的条目,因为我也会为已经加载的节点获取它们(从我的测试中它将占到调用的大约75%).

问题

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

Joh*_*nFx 6

如果它快速运行,您的问题可能在于重复调用该过程的数量.有没有办法可以修改存储过程和代码,以便在一次调用中返回应用程序所需的所有结果?

优化在不到2毫秒内运行的查询可能不是一项富有成效的工作.我怀疑你能通过查询调整来削减超过几分之一毫秒的时间.