0

目前有一个 sql 函数可以进行大量计算,我想知道以下是否是一个很好的替代品。我正在考虑构建一个调用 sql server 并提取数据并将其转储到数据表中的 C# 前端应用程序。从那里,我会将数据作为列表或向量(来自 sqldataadaptor 类的行)提供给 C++,这对于计算来说会更好。这里有一些假设。

1.必须在C#中完成,唯一的问题是是否引入C++

2.Sql函数目前对具有其唯一分组依据的数据进行3或4个选择语句(最多10个参数)

- 所以我应该将 C# 中的数据提供给 C++ 预组(或者改为按顺序排序?)并让 C++ 通过构建某种树形图或字典并遍历表来处理这个问题。在 C# 中执行 sql 语句很容易,并且已经将数据全部分组,但这使得 C++ 工作有些无用,而且可能是细粒度的

3.我试图替换的sql中的计算格式如下

  select a = exp(sum(log(x))),
     b = exp(sum(log(x))),
     c = exp(sum(log(y))),
     d = exp(sum(log(z))),
     e = exp(sum(log(u)))
  from data_table
  group by e,f,g,h,k

没什么太复杂的,非常基础的数学。

-再一次,在 C# 中执行此语句很容易,只返回分组的元素,但这意味着 sum() 和 log() 将在 C# 中完成,而 C++ 变得无用。但是,如果每次迭代我的表中有数千甚至可能数万行,并且每天运行多次,那么 C++ 在数学方面是否有任何优势(我的直觉告诉我不是真的)。

4.上述计算对应于 1 个“帐户”,每个帐户将有数百个帐户,并且 data_table 将有数千行,如果不是更多行,这可能会 24/7 每小时运行一次。

C# 重写是不可避免的,但真的有任何理由利用 C++ 来提高速度。它主要是为了速度,可能是为了未来的维护而解耦,但总体速度。如果我使用 C++,这将是要走的路吗?什么数据结构最适合处理这些数据并模拟它的一些 sql 功能。我基本上需要分组,然后非常快速地迭代它。有没有其他选择?C++ 是否感到被迫并且完全没有必要。谢谢。

4

2 回答 2

2

如果在 C# 或 C++ 中执行这种计算有任何收获,我会感到非常惊讶。将数据从 SQL 服务器传输到 C# 或 C++ 程序所需的时间将远远超过速度差异。请记住,SQL 服务器仍然使用您的 C++ 或 C# 代码将使用的相同 C 或 C++ 库(或至少一个非常相似的库),因此实际explog计算本身的速度将非常相似。开销来自 SQL 元素的解析。而且我认为根本不会有太大的不同。

如果您真的认为这是一个问题(我没有,但我不负责您正在做的工作......),我建议您尝试构建一个测试用例,其中包含一些具有实际值的表和实际大小(可能更大一些),然后比较计算值的速度并直接获取值(在纯 SQL 代码中 - 我假设有一个 SQL 命令行工具可以使用,或者一些网络-interface 或其他允许您执行计算的东西)。也许也只返回sum这些值。

编辑:我写了一些 PHP(因为我几乎已经在我的机器上安装了 PHP + MySQL 环境)。[不,这些不是我的用户名/密码组合——我不会在这样的公共服务器上发布它!]

<?php

$dbconnect = mysql_connect("localhost", "username", "password");
if (!$dbconnect)
{
    die('Could not connect: ' . mysql_error());
}
mysql_select_db("test", $dbconnect) 
    or die ("Couldn't connect to database: " . mysql_error() );

echo "Argv[1]=" . $argv[1] . "\n";


if ($argv[1] == "Create")
{
    $rm = getrandmax();
    for($i = 0; $i < 100000; $i++)
    {
        $a = rand() / $rm;
        $b = rand() / $rm;
        $c = rand() / $rm;
        $d = rand() / $rm;
        $e = rand() / $rm;
        $f = rand() / $rm;
        $sql = "INSERT INTO test1 (id, a, b, c, d, e, f) VALUES (" 
            . $i . 
            ", " .  $a . ", " . $b . ", " . $c . ", " . $d . ", " . $e
            . ", " . $f . ");";
        if (mysql_query($sql, $dbconnect) === false)
        {
            die("Could not add element " . mysql_error());
        }
    }
}

if ($argv[1] == "ExpSumLog")
{
    $sql = "SELECT exp(sum(log(a))) AS a1,
                 exp(sum(log(b))) AS b1,
                 exp(sum(log(c))) AS c1,
                 exp(sum(log(d))) AS d1,
                 exp(sum(log(e))) AS e1
          FROM test1
          GROUP BY e,f,id";
    $result = mysql_query($sql, $dbconnect) or die("Failed " . mysql_error());
    $count = 0;
    $sum = 0;
    while($row = mysql_fetch_assoc($result))
    {
        $count++;
        $sum += $row['a1'];
    }

    echo "Sum=" . $sum . ", count=" . $count . "\n";
}


if ($argv[1] == "Sum")
{
    $sum = 0;
    $sql = "SELECT sum(a) AS a1,
                 sum(b) AS b1,
                 sum(c) AS c1,
                 sum(d) AS d1,
                 sum(e) AS e1
          FROM test1
          GROUP BY e,f,id";
    $result = mysql_query($sql, $dbconnect) or die("Failed " . mysql_error());
    $count = 0;
    while($row = mysql_fetch_assoc($result))
    {
        $count++;
        $sum += $row['a1'];
    }

    echo "Sum=" . $sum . ", count=" . $count . "\n";
}

if ($argv[1] == "List")
{
    $sum = 0;
    $sql = "SELECT * FROM test1;";
    $result = mysql_query($sql, $dbconnect) or die("Failed " . mysql_error());
    $count = 0;
    while($row = mysql_fetch_assoc($result))
    {
        $count++;
        $sum += $row['a'];
    }

    echo "Sum=" . $sum . ", count=" . $count . "\n";
}

if ($argv[1] == "SumA")
{
    $sum = 0;
    $sql = "SELECT sum(a) FROM test1;";
    $result = mysql_query($sql, $dbconnect) or die("Failed " . mysql_error());
    $count = 0;
    while($row = mysql_fetch_assoc($result))
    {
        $count++;
        $sum += $row['sum(a)'];
    }

    echo "Sum=" . $sum . ", count=" . $count . "\n";
}

if ($argv[1] == "ExpSumLogA")
{
    $sum = 0;
    $sql = "SELECT sum(exp(log(a))) AS a1 FROM test1;";
    $result = mysql_query($sql, $dbconnect) or die("Failed " . mysql_error());
    $count = 0;
    while($row = mysql_fetch_assoc($result))
    {
        $count++;
        $sum += $row['a1'];
    }
    echo "Sum=" . $sum . ", count=" . $count . "\n";
}   
?>

创建大约需要 55 分钟......幸运的是,其他步骤要快得多。

Argv[1]=ExpSumLog
Sum=50017.011061374, count=100000

real    0m1.102s
user    0m0.289s
sys 0m0.066s
Argv[1]=Sum
Sum=50017.011061374, count=100000

real    0m1.004s
user    0m0.278s
sys 0m0.055s
Argv[1]=List
Sum=50017.011061374, count=100000

real    0m0.993s
user    0m0.322s
sys 0m0.060s
Argv[1]=SumA
Sum=50017.011061374, count=1

real    0m0.068s
user    0m0.019s
sys 0m0.012s
Argv[1]=ExpSumLogA
Sum=50017.011061374, count=1

real    0m0.095s
user    0m0.024s
sys 0m0.017s

如您所见,执行实际计算所需的时间远少于复制所有数据所需的时间。并且将数据计算为 sum(exp(log(a))) 和 sum(a) 之间的差异略有不同(但始终不同 - ExpSumLogA 和 SumA 的每次运行慢约 20-30 毫秒)。

为了证明数据传输是重点,我添加了以下四个变体:

if ($argv[1] == "SortedA")
{

    $sum = 0;
    $sql = "SELECT a AS a1 FROM test1 ORDER BY a;";
    $result = mysql_query($sql, $dbconnect) or die("Failed " . mysql_error());
    $count = 0;
    while($row = mysql_fetch_assoc($result))
    {
        $count++;
        $sum += $row['a1'];
    }
    echo "Sum=" . $sum . ", count=" . $count . "\n";
}

if ($argv[1] == "SortedExpLogA")
{

    $sum = 0;
    $sql = "SELECT exp(log(a)) AS a1 FROM test1 ORDER BY a;";
    $result = mysql_query($sql, $dbconnect) or die("Failed " . mysql_error());
    $count = 0;
    while($row = mysql_fetch_assoc($result))
    {
        $count++;
        $sum += $row['a1'];
    }
    echo "Sum=" . $sum . ", count=" . $count . "\n";
}

if ($argv[1] == "UnsortedA")
{

    $sum = 0;
    $sql = "SELECT a AS a1 FROM test1;";
    $result = mysql_query($sql, $dbconnect) or die("Failed " . mysql_error());
    $count = 0;
    while($row = mysql_fetch_assoc($result))
    {
        $count++;
        $sum += $row['a1'];
    }
    echo "Sum=" . $sum . ", count=" . $count . "\n";
}

if ($argv[1] == "UnsortedExpLogA")
{

    $sum = 0;
    $sql = "SELECT exp(log(a)) AS a1 FROM test1;";
    $result = mysql_query($sql, $dbconnect) or die("Failed " . mysql_error());
    $count = 0;
    while($row = mysql_fetch_assoc($result))
    {
        $count++;
        $sum += $row['a1'];
    }
    echo "Sum=" . $sum . ", count=" . $count . "\n";
}

显然,这些变体比导出所有数据运行得更快,但比“只返回一个值”慢,而且确实如此。

Argv[1]=SortedA
Sum=50017.011061375, count=100000

real    0m0.375s
user    0m0.194s
sys 0m0.027s
Argv[1]=SortedExpLogA
Sum=50017.011061375, count=100000

real    0m0.394s
user    0m0.202s
sys 0m0.023s

Argv[1]=UnsortedA
Sum=50017.011061374, count=100000

real    0m0.353s
user    0m0.206s
sys 0m0.018s
Argv[1]=UnsortedExpLogA
Sum=50017.011061374, count=100000

real    0m0.383s
user    0m0.223s
sys 0m0.025s

可以看到,Sorted 比 Unsorted 花费的时间稍微长一点(预计,如果你要排序 100K 个项目,它会增加一些时间),而 ExpLog 变体比“just return”慢一点A”变体。这是相当一致的。

于 2013-09-16T16:42:51.240 回答
2

C++ 的性能提升不足以保证额外的复杂性,尤其是在您解决问题之前。先用 C#,然后看看你的需求是否已经得到满足。
就像 ilent2 在评论中所说的那样,您始终可以在 C++ 中进行核心计算并从 C# 调用 - 重用大部分 C# 代码。

另外,看看你的问题,看起来你 99% 的速度将来自于你如何实现解决方案,而不是你选择了哪种语言。去拿他们!

于 2013-09-16T16:36:19.507 回答