SQL查询在C ++应用程序中最小化/缓存

时间:2011-08-01 13:06:40

标签: c++ sql qt lazy-evaluation database-caching

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

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

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

  1. 减少查询次数
  2. 快速查询
  3. 解决(1)

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

    解决(2)

    例如,通过保持数据库的本地同步副本运行,可以加快查询速度。但是,我在客户端计算机上运行的可能性并不大,例如与服务器上的数据库类型完全相同。因此,本地副本例如是SQLite数据库。这也意味着我无法使用特定于数据库供应商的解决方案。 我有什么选择?在这种情况下,什么能为人们带来好处?

    我主要担心的是:

    • 陈旧数据:有许多可以想象的查询以这样的方式更改数据库,即禁止对具有陈旧数据的用户执行操作。
    • 可维护性:我可以在这个新图层中融合多少?如果它不必知道关于我的内部惰性对象系统以及关于每个对象和可能的查询的一切,显然会更好。

    最后的问题

    什么是最小化查询成本的好方法?良好的意义某种组合:可维护,易于实现,而不是特定的aplication。如果它选择任何2,那么就这样吧。我想听听人们谈论他们的经历以及他们为解决这些问题所做的工作。

    正如你所看到的,我已经想到了一些问题和处理它的方法,但我不知道什么是一个合理的方法。由于很可能涉及很多工作并且对程序中的许多层进行了密集的更改(希望尽可能少),我想在此之前向所有专家询问,然后再就此事做出最终决定。我也可以忽略一个非常简单的解决方案,在这种情况下,非常感谢指向它的指针!

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

    *注意:我已检查过类似问题的用户的问题,这些问题并不完全符合我的问题:例如Suggestion on a replication scheme for my use-case?Best practice for a local database cache?

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

    注意“懒惰”

    我的代码看起来像的一个小例子(当然简化):

    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
    }
    

1 个答案:

答案 0 :(得分:2)

乍一看,您看起来有两个相互冲突的目标:查询速度,但总是使用最新数据。因此,您可能应该回到需要帮助决定这一点。

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

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