在我的应用上进行负载测试时,我看到了一个巨大的减速。 我有一个大约需要350ms才能运行的查询,但我并行运行了8次(更不用说32次),它最多可以运行2.5秒。
我在分析器上验证了执行确实占用了时间。
查询:
SELECT SUM([_Facts_].[Sales]) [_measures___Sum Sales_], [_Date_].[year] [_Date___year_]
FROM [pp].[Facts] [_Facts_], [pp].[Date] [_Date_]
WHERE [_Facts_].[dateKey] = [_Date_].[dateKey]
GROUP BY [_Date_].[year]
ORDER BY [_Date_].[year] ASC
我正在运行8个并行进程,按顺序进行10次调用。 对于1个并行,我得到:
360, 350, 345, 360, 365, 360, 395, 786, 395, 370, avg:408
8平行:
515, 1571, 1471, 1326, 1862, 2478, 1922, 3098, 2413, 2032, 2773, 3048, 2453, 2092, 2077, 3359, 2898, 2733, 3018, 2483, 1887, 3023, 3088, 3724, 2317, 2753, 2643, 3284, 3299, 2418, 1907, 1862, 2498, 2838, 2518, 3203, 2613, 2207, 3434, 2613, 3198, 2257, 2593, 2448, 2518, 2968, 2828, 2122, 2963, 2212, 3299, 2988, 3153, 2803, 2157, 2543, 2758, 2998, 2538, 2257, 2788, 2443, 2082, 2613, 3173, 4205, 2603, 2387, 1747, 3854, 3068, 2788, 2603, 3103, 2703, 3198, 1832, 1421, 2217, 1326
平均:
2535, 2523, 2571, 2627, 2689, 2469, 2521, 2610
当平行进入16时,它甚至更多。
我尝试在MySql上进行测试并得到相同的跳转(不同的测试时间,但并行时至少慢4倍)。
这些数据库无法处理负载吗?!
在C#和Java中都会发生这种情况: C#:
class Program
{
static void Main(string[] args)
{
Parallel.For(0, 8, i => run());
}
static void run()
{
using (var conn = new SqlConnection("Data Source=.;Initial Catalog=;User ID=;Password="))
{
conn.Open();
var cnt = 10;
long avg = 0;
for (int i = 0; i < cnt; i++)
{
var sw = DateTime.Now.Ticks;
using (var cmd = new SqlCommand("SET ARITHABORT ON", conn))
{
cmd.CommandText =
"SELECT SUM([_Facts_].[Sales]) [_measures___Sum Sales_], [_Date_].[year] [_Date___year_]\n" +
"FROM [pp].[Facts] [_Facts_], [pp].[Date] [_Date_]\n" +
"WHERE [_Facts_].[dateKey] = [_Date_].[dateKey] \n" +
"GROUP BY [_Date_].[year]\n" +
"ORDER BY [_Date_].[year] ASC";
using (var reader = cmd.ExecuteReader())
{
var x = 0;
while (reader.Read())
{
x++;
}
reader.Close();
}
}
var dif = (DateTime.Now.Ticks - sw) / 1000;
avg += dif;
Console.WriteLine(dif);
}
conn.Close();
Console.WriteLine("avg:" + avg / cnt);
}
}
}
爪哇:
@Test
public void asdf() throws SQLException {
Runnable r = () -> {
try (Connection conn = DriverManager.getConnection("jdbc:sqlserver://;databaseName=", "", "")) {
long avg = 0;
for (int i = 0; i < 10; i++) {
try (Statement statement = conn.createStatement()) {
StopWatch sw = new StopWatch();
sw.start();
ResultSet resultSet = statement.executeQuery("SELECT SUM([_Facts_].[Sales]) [_measures___Sum Sales_], [_Date_].[year] [_Date___year_]\n" +
"FROM [pp].[Facts] [_Facts_], [pp].[Date] [_Date_]\n" +
"WHERE [_Facts_].[dateKey] = [_Date_].[dateKey] \n" +
"GROUP BY [_Date_].[year]\n" +
"ORDER BY [_Date_].[year] ASC");
int x = 0;
while (resultSet.next()) {
x++;
}
sw.stop();
avg+=sw.getTime();
System.out.println(sw);
}
}
System.out.println(avg/10);
} catch (SQLException e) {
e.printStackTrace();
} finally {
}
};
ExecutorService executor = Executors.newFixedThreadPool(8);
for (int i = 0; i < 8; i++) {
executor.execute(r);
}
try {
executor.shutdown();
executor.awaitTermination(12312313, TimeUnit.MINUTES);
} catch (InterruptedException e) {
e.printStackTrace();
}
}
更多信息
这两个表是~1,000行和〜420,000行。连接约为420,000行,结果为3行。
在date.dateKey和FK上有关于事实的PK。这些是表格,而不是观点。
我查看了探查器以确认持续时间是查询的实际执行时间,而不是应用程序的运行时间。
SqlServer有16个内核,所以我希望8个查询并行运行而不会堆叠。
在服务器上,1次查询的CPU最高可达50%。对于8,它达到了95%。
网络/内存/ IO似乎没有太大变化。