【发布时间】:2012-12-25 16:12:49
【问题描述】:
我正在构建将数据库与 3 个表(Worker、Task、TaskStep)一起使用的程序 我有一种方法可以为特定工人获取日期和构建报告 具体日期的任务和步骤。
数据库结构如下:
MySQL 5.2
Worker 表列:
workerID(VARCHAR(45)),
name(VARCHAR(45)),
age(int),
...
Tasks 表列:
TaskID(VARCHAR(45)),
description(VARCHAR(45)),
date(DATE),
...
TaskSteps 表列:
TaskStepID(VARCHAR(45)),
description(VARCHAR(45)),
date(DATE),
...
在任何表上都没有索引
问题是它非常非常慢!! (约 20 秒)
代码如下:
using WorkerDailyReport = Dictionary<task, IEnumerable<taskStep>>;
private void Buildreport(DateTime date)
{
var report = new WorkerDailyReport();
// Load from DB
var sw = new Stopwatch();
sw.Start();
var startOfDay = date.Date;
var endOfDay = startOfDay.AddDays(1);
var db = new WorkEntities();
const string workerID = "80900855";
IEnumerable<task> _tasks = db.task
.Where(ta => ta.date >= startOfDay &&
ta.date < endOfDay &&
ta.workerID == workerID)
.ToList();
sw.Stop();
Console.WriteLine("Load From DB time - " + sw.Elapsed +
", Count - " + _tasks.Count());
// Build the report
sw.Restart();
foreach (var t in _tasks)
{
var ts = db.taskStep.Where(s => s.taskID == task.taskID);
report.Add(t, ts);
}
sw.Stop();
Console.WriteLine("Build report time - " + sw.Elapsed);
// Do somthing with the report
foreach (var t in report)
{
sw.Restart();
foreach (var subNode in t.Value)
{
// Do somthing..
}
Console.WriteLine("Do somthing time - " + sw.Elapsed +
", Count - " + t.Value.Count());
}
}
如你所见,我在每个部分都放了秒表来检查需要这么长时间 这是结果:
1)
如果我像上面那样运行代码:
控制台:
Load From DB time - 00:00:00.0013774, Count - 577
Build report time - 00:00:03.6305722
Do somthing time - 00:00:07.7573754, Count - 21
Do somthing time - 00:00:08.2811928, Count - 11
Do somthing time - 00:00:07.8715531, Count - 14
Do somthing time - 00:00:08.0430597, Count - 0
Do somthing time - 00:00:07.7867790, Count - 9
Do somthing time - 00:00:07.3485209, Count - 39
.........
内部 foreach 运行大约需要 7-9 !秒不要再跑过去 40 条记录。
2)
如果我只改变一件事,在第一个查询之后添加 .ToList() 当我从数据库加载工作任务时,它会改变 一切。
控制台:
Load From DB time - 00:00:04.3568445, Count - 577
Build report time - 00:00:00.0018535
Do somthing time - 00:00:00.0191099, Count - 21
Do somthing time - 00:00:00.0144895, Count - 11
Do somthing time - 00:00:00.0150208, Count - 14
Do somthing time - 00:00:00.0179021, Count - 0
Do somthing time - 00:00:00.0151372, Count - 9
Do somthing time - 00:00:00.0155703, Count - 39
.........
现在从数据库加载需要更多时间,4 秒以上。 但内置报告时间约为~1ms 每个内部 foreach 大约需要 10 毫秒
第一种方法是不可能的(577 * ~8 秒)和第二种选择 也很慢,我看不到你。
知道这里发生了什么吗?
1) 为什么ToList() 这么慢?
2) 为什么没有ToList()、内部foreach 和构建报告会变慢?
我怎样才能让它更快?
谢谢。
【问题讨论】:
-
对于这类问题,分享更多有关数据库结构(列、索引等)的信息会非常有益。
-
已编辑问题,希望对您有所帮助:)
-
据我所知:第一次访问数据时会评估 Linq。在您的情况下,这是“ToList()”或内部 foreach。如果您使用 Linq Join 而不是 Where,您可能会更快。 (请原谅我目前无法提供答案,因为我这里没有开发环境)
-
奇怪的是,当我从 MySQL 工作台使用相同的参数运行 SQL 查询时,它需要大约 1 秒。
标签: c# performance linq entity-framework-4