ZODB python: как избежать создания базы данных только с одной большой записью? - PullRequest
0 голосов
/ 21 мая 2018

Я впервые использую модуль базы данных Python ZODB.Учебное пособие (http://www.zodb.org/en/latest/tutorial.html) вводит меня в заблуждение по поводу определенного аспекта поведения базы данных ZODB: как избежать случайного создания базы данных только с одной очень большой записью? Я объясню шаг за шагом мое приложениемой нынешний подход к базе данных и откуда возникла путаница.


1. Item-object

База данных, которую я хочу сохранить, целиком состоит из Элемент -объекты, определенные следующим образом (немного упрощенно):

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


Приложение создает один такой объект Item при запуске. Во время приложения этот объект Item создает «потомки» (которые также являются самими объектами Item). Этот процесс продолжается некоторое время, так чтоследующая объектная структура находится в памяти:

enter image description here


Эта конструкция может легко состоять из 20 000 Item -объектов.Я хочу сохранить их в базе данных.


2.Как сохранить эту структуру в базе данных ZODB

Чтобы сохранить эту структуру объектов Item в базе данных, я следую следующим инструкциям из учебника:

Хранениеobjects
Чтобы сохранить объект в ZODB, мы просто присоединяем его к любому другому объекту, который уже находится в базе данных.Следовательно, корневой объект функционирует как точка привязки к загрузке.Корневой объект предназначен для использования в качестве пространства имен для объектов верхнего уровня в вашей базе данных.
[Цитируется из ZODB Tutorial 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()


3.Проблема с хранением всего в корне

Однако - при чтении учебника - у меня складывается впечатление, что мой текущий подход не очень хорош:

(пожалуйстаобратите внимание, что на этом этапе в учебнике был рассмотрен пример создания Account -объектов для хранения в базе данных ZODB)

Мы могли бы хранить Account -объекты непосредственно в корневом объекте:

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()

Сноска 3 :
Корневой объект - это простой простой постоянный объект, который хранится в одной записи базы данных.Если вы сохраните в нем много объектов, запись в его базе данных станет очень большой, что приведет к неэффективности обновлений и неэффективному использованию памяти.

Сноска означает, что я просто создаюбаза данных с одной большой записью - это, конечно, самая неэффективная база данных, которую вы только можете себе представить.


4.Что меня смущает из-за

Хорошо, я почти уверен, что следующий подход очень плох (и осужден приведенным выше предупреждением):

enter image description here


Но относится ли это предупреждение (не хранить все в корне) к моему случаю?Например:

enter image description here

Другими словами, будет ли мой подход создать базу данных с одной большой записью (очень неэффективно)?Или это создаст хорошую базу данных с одной записью на Item -объект?


Примечание:
Я не уверен, еслиэто актуально, но я перечислю здесь свои системные характеристики:

  • Windows 10, 64-битная
  • Python 3.6.3
  • ZODB 5.4.0 (is isпоследняя версия на сегодня - 21 мая 2018 г.)

1 Ответ

0 голосов
/ 21 мая 2018

Нет, это не неэффективно.ZODB создает отдельные записи для каждого Persistent экземпляра .Позже эти записи загружаются по требованию при доступе к ним.

Из того же учебника, на который вы ссылаетесь:

Подклассы Persistent предоставляют ряд функций:

[...]

  • Данные будут сохранены в отдельной записи базы данных.

Это полностью прозрачно для вашего приложения.Ваша первая транзакция будет большой, но последующие транзакции будут записывать изменения только для отдельных элементов по мере их изменения.

...