代码之家  ›  专栏  ›  技术社区  ›  K.Mulier

Zodbpython:如何避免创建只有一个大条目的数据库?

  •  3
  • K.Mulier  · 技术社区  · 7 年前

    我用的是 zodb python数据库 第一次使用模块。教程( http://www.zodb.org/en/latest/tutorial.html )使我对Zodb数据库行为的某个方面感到困惑:如何避免意外地创建只有一个非常大的条目的数据库?我将一步一步地解释我的应用程序、我当前的数据库方法以及混淆的来源。


    1。项目对象

    我要保存的数据库完全由 项目 -对象,定义如下(稍微简化一点):

    class Item(Persistent):
        def __init__(self, name, *args, **kwargs):
            super().__init__(*args, **kwargs)
    
            # 1. Persistent variables
            # ------------------------
            self.__name = name
            self.__myList = PersistentList()   # <- list can hold other Item-objects
    
            self.__myVar01 = None
            self.__myVar02 = None
            self.__myVar03 = None
    
            # 2. Non-persistent variables
            # ----------------------------
            self._v_myVar01 = None
            self._v_myVar02 = None
            self._v_myVar03 = None
    

    视觉表现如下:

    enter image description here


    应用程序在启动时构造一个这样的项对象。在应用程序期间,此项对象将创建“子对象”(也是项对象本身)。这个过程会持续一段时间,这样以下对象结构就在内存中:

    enter image description here


    这个建筑很容易由20000个组成。 项目 -对象。所以我想把它们保存在数据库中。


    2。如何将此结构保存到zodb数据库

    要在数据库中保存项目对象的这种结构,我遵循本教程中的以下指导原则:

    存储对象
    要在zodb中存储对象,我们只需将其附加到数据库中已经存在的任何其他对象。因此,根对象充当引导点。根对象将用作数据库中顶级对象的命名空间。
    [引自ZODB教程 http://www.zodb.org/en/latest/tutorial.html ]

    以下函数创建一个新数据库(从顶级项开始)并将其保存到硬盘驱动器:

    from ZODB.FileStorage import FileStorage
    from ZODB import DB
    from persistent import Persistent
    import transaction
    
    # Call this function to save the database
    # to the harddrive and close it.
    # ----------------------------------------
    def save_database_and_close():
        transaction.commit()
        conn.close()
        db.close()
    
    # Call this function to create a new
    # database, starting from a root-item
    # ------------------------------------
    def create_database(root_item):
        storage = FileStorage("C:/mytest/mydb.db")
        db = DB(storage)
        conn = db.open()
        root = conn.root()
        root.myRootItem = root_item
        transaction.commit()
    


    三。在根目录上存储所有内容的问题

    但是,当继续阅读教程时,我觉得我目前的方法不是很好:

    (请注意,在这一点上,本教程介绍了 帐户 -要存储在zodb数据库中的对象)

    我们可以储存 帐户 -直接在根对象上的对象:

    import account
    
    # Probably a bad idea:
    root.account1 = account.Account()
    

    但如果要存储许多对象,则需要使用集合对象 3 :

    import account, BTrees.OOBTree
    
    root.accounts = BTrees.OOBTree.BTree()
    root.accounts['account-1'] = Account()
    

    脚注 :
    根对象是一个仙女般简单的持久对象,存储在单个数据库记录中。如果您在其中存储了许多对象,它的数据库记录将变得非常大,从而导致更新效率低下,并导致内存使用效率低下。

    脚注意味着我只是在创建一个有一个大条目的数据库——这当然是你能想象到的最低效的数据库类型。


    4。我对什么感到困惑

    好吧,我很确定下面的方法是非常糟糕的(并受到上述警告的谴责):

    enter image description here


    但是这个警告(不是把所有东西都存储在根目录上)也适用于我的案例吗?这样地:

    enter image description here

    换句话说, 我的方法会创建一个只有一个大条目(非常低效)的数据库吗?或者它会创建一个不错的数据库,每个数据库有一个条目 项目 -对象?


    注:
    我不确定它是否相关,但我将在这里列出我的系统规格:

    • Windows 10,64位
    • 蟒蛇3.6.3
    • ZODB 5.4.0(是截至2018年5月21日的最新版本)
    1 回复  |  直到 7 年前
        1
  •  2
  •   Martijn Pieters    7 年前

    不,这不是低效的。ZODB创建 每个单独的条目 Persistent 实例 . 这些条目稍后会在您访问时按需加载。

    从您链接到的同一个教程:

    子类别化 持久的 提供了许多功能:

    […]

    • 数据将保存在自己的数据库记录中。

    这对您的应用程序是完全透明的。您的第一个事务将很大,但随后的事务将只在您更改单个项目时写出对它们的更改。