【问题标题】:c# clr udf scan sql tablec# clr udf 扫描sql表
【发布时间】:2011-10-24 08:45:36
【问题描述】:

我想创建 CLR UDF 来扫描 SQL 表并读取每一列并对所有数据求和 每列(我正在处理大型数据集,例如 >1000 列和 20,000,000>rows)。

我想比较一下申请每列SUM(COLUMN_NAME) SQL 函数和并行化for loop

所以 SQL 看起来像

SELECT SUM(COLUMN_1),SUM(COLUMN_2),SUM(COLUMN_3),...,SUM(COLUMN_1000)

我怎样才能做到CLR UDF in C#

我打算使用一个数组,所以每次我阅读该行时,我都会添加它: array[i]+= sqlValue;

如何做到这一点,以便我可以在stored proc 中执行它们?

表格

column_1  column_2 column_3   .... column_1000
---------------------------------------------
     451      57     253                 135
     251      77     356                 965
     481      15     323                 655  
     452      15     135                 665
    ... 
    ...20,000,000 more rows

【问题讨论】:

  • 您的 CLR UDF 看起来如何?你已经尝试了什么?创建 CLR UDF 有据可查。
  • 按列扫描表并并行执行for循环?你有例子吗?

标签: c# sql-server stored-procedures


【解决方案1】:

所以你想要实现的是做一千个SELECT column_x FROM table,每列一个,然后手动求和。

这意味着到数据库的 1000 个并行连接都在同一个表的同一行中工作,相互锁定(直到您使用 with nolock)。

SELECT sum(column_1), sum(column_2), ... 的好处。我看不到一个,我相信你正在尝试的将比让 SQL Server 做它最擅长的事情慢很多。

编辑:

根据您的要求,这里有一个快速的'n'dirty 示例,由于我目前手头没有 SQL 服务器,因此未进行测试。我假设列是long 类型,结果是decimal 类型。

public partial class UserDefinedFunctions
{
    private static string GetCommandText(int column)
    {
        return string.Format("select column_{0} from table", column);
    }

    [Microsoft.SqlServer.Server.SqlFunction(
        DataAccess = DataAccessKind.Read,
        TableDefinition = "result decimal",
        FillRowMethodName = "FillRow",
        SystemDataAccess = SystemDataAccessKind.Read)]
    public static IEnumerable fnSum(int columnNo)
    {
        var values = new List<long>();

        using (var cmd = new SqlCommand(GetCommandText(columnNo), new SqlConnection("context connection=true")))
        {
            cmd.Connection.Open();
            using (var reader = cmd.ExecuteReader(CommandBehavior.SingleResult | CommandBehavior.CloseConnection))
            {
                while (reader.Read())
                {
                    values.Add(reader.GetInt64(0));
                }
            }
        }

        return list;
    }

    private static void FillRow(object obj, out decimal result)
    {
        var values = (List<long>)obj;

        result = values.Sum(value => (decimal) value);
    }
}

【讨论】:

  • 也许只用4个线程,我也想做其他复杂的公式,求和很容易,但是,sqr或log呢....我需要的是clr udf c#的例子扫描列...你能指出一个教程吗?
  • @cMinor,你不能用CREATE AGGREGATE创建你自己的聚合函数并使用mathematical functions offered by T-SQL吗?
  • 我刚刚确认您不能(也不应该)在 SQL CLR 函数中生成多个线程。
  • @VVS: 线程问题已了解....我也会尝试,但我有兴趣通过 c# 进行,如何按列或行扫描?
  • +1,我同意你的看法:magnitudes slower than letting SQL Server doing what it does best.
【解决方案2】:

只是一个猜测,但如果您的“真正”问题是您需要经常运行一个慢速查询来扫描整个表,对每一列执行 SUM(),那么实现这一点的最快和最简单的方法是持久化聚合看法。它基本上会在 INSERT/DELETE/UPDATE 上产生 SUM() 开销,但 SELECT 速度是即时的。

你基本上会做出这样的看法:

CREATE VIEW MyView WITH SCHEMABINDING AS
SELECT SUM(col1) AS SumCol1, SUM(col2) AS SumCol2, ...
FROM dbo.YourTable
GO
CREATE UNIQUE CLUSTERED INDEX idx_MyView ON MyView(SumCol1,SumCol2)

【讨论】:

    猜你喜欢
    • 1970-01-01
    • 2012-01-31
    • 2011-10-24
    • 1970-01-01
    • 2010-09-18
    • 1970-01-01
    • 2011-01-27
    • 1970-01-01
    • 2013-11-02
    相关资源
    最近更新 更多