5

我正在用C++/Qt编写一个项目,它能够连接到QtSQL ( http://doc.qt.nokia.com/latest/qtsql.html )支持的任何类型的SQL数据库。这包括本地服务器和外部服务器

但是,当有问题的数据库是外部的时,查询的速度开始成为一个问题(UI 慢,...)。原因:存储在数据库中的每个对象都是延迟加载的,因此每次需要属性时都会发出查询。屏幕上平均显示大约 20 个对象,每个对象显示大约 5 个属性。这意味着,对于我展示的每个屏幕,都会执行大约 100 个查询。查询在数据库服务器本身上执行得非常快,但是在网络上运行的实际查询的开销是相当大的(以秒为单位测量整个屏幕)。

我一直在考虑解决问题的几种方法,最重要的方法似乎是(根据我):

  1. 减少查询
  2. 使查询更快

应对 (1)

  • 我可以找到某种方法来延迟属性的实际获取(启动事务),然后当程序员编写endTransaction()时,数据库会尝试一次性获取所有内容(使用 SQL UNION 或循环......) . 这可能需要对惰性对象的工作方式进行相当多的修改,但如果人们评论说这是一个不错的解决方案,我认为它可以优雅地解决。如果这个解决方案足够加速一切,那么甚至可能不需要精心设计的缓存方案,从而省去很多麻烦
  • 我可以尝试通过在一个查询中获取所有请求的所有对象的全部属性数据来预加载属性数据,从而有效地使它们成为non-lazy。当然,在这种情况下,我将不得不担心过时的数据。我如何在不至少向外部数据库发送一个查询的情况下检测陈旧数据?(注意:发送查询以检查每个属性检查的陈旧数据会在实际发现数据陈旧时提供最佳情况 0x 性能提升和最坏种姓 2x 性能下降

应对 (2)

例如,可以通过保持数据库的本地同步副本运行来加快查询速度。但是,我在客户端机器上并没有太多的可能性来运行例如与服务器上的数据库类型完全相同的数据库类型。因此,本地副本例如是 SQLite 数据库。这也意味着我不能使用特定于 db-vendor 的解决方案。我在这里有什么选择?在这种情况下,什么对人们有效?

担心

我主要担心的是:

  • 陈旧数据:可以想象有很多查询会更改数据库,从而禁止对具有陈旧数据的用户而言似乎可能的操作。
  • 可维护性:我可以在这个新层中松散地耦合到什么程度?如果它不必了解我的内部惰性对象系统以及每个对象和可能的查询的所有信息,那显然会更好

最后一个问题

什么是最小化查询成本的好方法?好的意思是某种组合:可维护,易于实现,不太特定于应用程序。如果归结为选择任何2,那就这样吧。我想听听人们谈论他们的经历以及他们为解决这个问题所做的事情。

如您所见,我已经想到了一些问题和处理方法,但是我不知道什么才是明智的方法。由于它可能涉及大量工作和对程序中许多层的密集更改(希望尽可能少),因此我考虑在对此事做出最终决定之前询问这里的所有专家。也有可能我只是忽略了一个非常简单的解决方案,在这种情况下,一个指向它的指针将不胜感激!

假设所有相关的服务器端调整都已完成(例如:MySQL 缓存、最佳索引,...)

*注意:我检查了有类似问题的用户的问题,但这些问题并不完全满足我的问题:关于我的用例的复制方案的建议?本地数据库缓存的最佳实践?例如)

如果需要任何其他信息来提供答案,请告诉我,我会及时更新我的​​问题。对任何拼写/语法错误表示歉意,英语不是我的母语。

关于“懒惰”的注意事项

我的代码的一个小例子(当然是简化的):

QList<MyObject> myObjects = database->getObjects(20, 40); // fetch and construct object 20 to 40 from the db

// ...some time later

// screen filling time!
foreach (const MyObject& o, myObjects) {
    o->getInt("status", 0);  // == db request
    o->getString("comment", "no comment!"); // == db request
    // about 3 more of these
}
4

1 回答 1

2

乍一看,您似乎有两个相互冲突的目标:查询速度,但始终使用最新数据。因此,您可能应该回退到您的需求来帮助在这里做出决定。

1) 与应用程序的使用相比,您的数据库几乎是静态的。在这种情况下,使用您的选项1b并预加载所有数据。如果数据可能在下面发生变化的可能性很小,只需为用户提供刷新缓存的选项(完全刷新或针对特定数据子集)。这样,慢速访问就掌握在用户手中。

2) 数据库变化相当频繁。在这种情况下,“也许”SQL 数据库不适合您的需求。您可能需要一个更高性能的动态数据库来推送更新而不是拉取。这样,当底层数据发生变化时,您的应用程序会收到通知,您将能够快速响应。但是,如果这不起作用,您需要编写查询以最小化 DB 库和 I/O 调用的数量。例如,如果您执行一系列select语句,您的结果应该按照您请求的顺序包含所有适当的数据。您只需要跟踪相应的选择语句是什么。或者,如果您可以使用更宽松的查询条件,以便它为您的简单查询返回多行,这也应该有助于提高性能。

于 2011-08-01T14:19:48.733 回答