目前有一个sql函数执行一堆计算,我想知道以下是否是一个很好的替代品。我正在考虑构建一个C#前端应用程序,它调用sql server并提取数据并将其转储到数据表中。从那里,我将数据作为列表或向量(来自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
真的没什么太复杂,非常基本的数学。
-Again,在C#中执行此语句很容易,只返回分组元素,但这意味着sum()和log()将在C#和C ++中完成无效。但是,如果每次迭代我的表中有数千行甚至数万行,并且每天运行多次,那么C ++在数学方面是否有任何优势(我的直觉告诉我并不是真的)。
4.上述计算对应1个“帐户”,每个帐户将有数百个帐户和data_table,如果不是更多行,则会有数千个,这可能会每小时24小时运行一次。
C#重写是不可避免的,但是真的有任何理由利用C ++来提高速度。它主要用于速度和可能的解耦,以便将来维护但总体速度。如果我使用C ++,那么这将是什么样的方式,哪种数据结构最适合处理这些数据并模拟它的一些sql功能。我基本上需要分组,然后非常快速地遍历它。还有其他选择吗? C ++是否感到被迫,完全没必要。谢谢。
答案 0 :(得分:2)
C ++不足以提高性能,以保证额外的复杂性,特别是在您解决问题之前。首先使用C#,然后查看是否已满足您的需求 就像ilent2在评论中说的那样,你总是可以用c ++进行核心计算,然后从C#调用 - 重用大量的C#代码。
另外,看看你的问题,看起来99%的速度将来自你实施解决方案的方式,而不是你选择的语言。去吧!
答案 1 :(得分:2)
如果在C#或C ++中执行这种计算有任何好处,我会非常惊讶。将数据从SQL服务器传输到C#或C ++程序所花费的时间远远超过速度差异。请记住,SQL Server仍然使用与C ++或C#代码相同的C或C ++库(或至少一个非常类似的库),因此实际的exp
和log
计算本身速度会非常相似。开销来自SQL元素的解析。而且我不相信会有太大的不同。
如果你真的认为这是一个问题(我没有,但是我不负责你正在做的工作......),我建议你尝试用一些表构建一个测试用例具有实际值和实际大小(可能更大),然后比较计算值的速度和直接获取值(在纯SQL代码中 - 我假设有一个SQL命令行工具,你可以使用,或某些网络界面或允许您执行计算的东西)。也许只返回sum
的值。
编辑:我写了一些PHP(因为我几乎已经在我的机器上安装了PHP + MySQL环境)。 [不,那些不是我的用户名/密码combinatin - 我不会在那样的公共服务器上发布它!]
<?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 ms)。
为了证明这是主要的数据传输,我添加了以下四种变体:
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变量比“只返回A”变种。这是相当一致的。