我正在使用C#(sharpdevelop)来访问firebird 2.5服务器。这非常有效。但是,我遇到了性能问题。 我有两个表,成员和交易存储谁买什么时候。要查看一段时间没有活动的人,我运行以下复合查询:
SELECT * FROM members M
WHERE exists (select 1 from transactions WHERE taDateTime >= '30.06.2013' and Memberid = M.ID)
因此,Members-table在字段ID上有一个主索引,而表事务在taDateTime和MemberID上都有indeces。
myConnection = new FbConnection(myConnectionString);
Connection.Open();
// property of a helper class, uses myConnection
// Then when I press the Search button:
// create the sql command, because the cut-off date is passed as a dbParam
IDbCommand aCmd = new FbCommand(sql, Connection);
IDataReader aReader = aCmd.ExecuteReader();
我现在在会员中有几个10'000个条目,在交易中有几个100'000个条目。如果我在flamerobin中运行此查询,则运行大约需要2.6秒。这不是惊心动魄,而是足够的。但是,如果我在C#中运行此查询,我只需要3分钟即可从通话中返回
FbCommand.ExecuteReader(SQL)。
我还没有对结果集进行循环,这纯粹是对ExecuteReader()
的调用。这需要做什么需要这么长时间?
我尝试过其他一些事情,因为通过添加ROWS
或FIRST
子句来限制结果数量,两者都没有效果。所以重要的不是结果的数量。
我试图将调用拆分为2个查询:首先找到DISTINCT(Transaction.MemberID)
,然后找到适合的成员,但是有太多的ID可以合理地传入第二个查询。
我甚至编写了一个首先找到MemberID的循环,然后为每个结果运行"SELECT * FROM Members where ID = xx"
,这比单个语句更快。那么什么使ExecuteReader的调用延迟这么长?
请帮助,我真的很茫然。
亲切的问候, 汉纳斯
答案 0 :(得分:0)
我应该通过评论而不是发布答案来澄清这一点,然而,作为一个新手,我不被要求提供更多信息(即评论)!!!
引用您的行“要查看谁没有一段时间没有激活我运行以下复合查询:”,在我看来,此方案中的正确查询应该是......
SELECT * FROM members M
where M.ID not in (select distinct memberid from transactions WHERE taDateTime >= '30.06.2013')
您撰写的查询将为您提供活跃的人。此外,它还会加载数据库服务器,处理几个10,000 * 100,000条记录。
如果您确实在某个日期之后找到不活跃的人,那么我给您的查询应该比之前的结果至少快100倍。我很想知道结果,无论如何都请让我知道。感谢。
答案 1 :(得分:0)
我同意@Ravi您的查询本身有一些边缘可能需要一些平滑。我在SQL中做得不够好,无法真正预测幕后发生的事情,但仅仅从我的直觉来看,我说你的陈述对我来说是“可疑的”......
但是那仍然不能单独回答你的问题,否则Flamerobin中的执行时间将与从代码执行时一样糟糕。出于这个原因,我希望你的代码中有些东西是罪魁祸首。如果您可以使用更多代码更新帖子,那就太棒了。
需要考虑的事项:
Prepare()
你的命令吗?如果你对数据库多次触发它,这也会给你带来性能提升。不要忘记,由于.NET代码在JIT编译器执行时需要初始化和分配,因此当第二次运行时,语句可能会运行得更快。试试这个并在第一次查询后第二次(或多次)运行查询。它有所不同吗?
答案 2 :(得分:0)
感谢所有的投入,伙计们!在你的建议中搜索一些关键字让我更详细地分析我的查询,从而发现错误:我的编程“秘密地”在查询结尾处添加了一个“ORDER BY Member.Name”子句,这是罪魁祸首。我一直在调查我的眼皮错过了:)无论如何,我发现了一篇非常有用的文章,用于理解和调整firebird中的查询,并且只能推荐给任何感兴趣的人:http://conferences.embarcadero.com/article/32256。亲切的问候,Hannes