Поддерживает ли GAE Datastore готовую загрузку? - PullRequest
2 голосов
/ 11 ноября 2010

Допустим, я хочу отобразить список книг и их авторов.В традиционном проектировании базы данных я бы выполнил один запрос для извлечения строк из таблицы Book, а также из связанной таблицы Author, шаг, известный как eager fetching .Это сделано для того, чтобы избежать страшной проблемы N + 1 select : если бы записи Author извлекались лениво, моей программе пришлось бы выдавать отдельный запрос для каждого автора, возможно столько же запросов, сколько книгв списке.

Предоставляет ли Google App Engine Datastore аналогичный механизм или проблема выбора N + 1 больше не актуальна на этой платформе?

1 Ответ

3 голосов
/ 11 ноября 2010

Я думаю, что вы неявно спрашиваете, поддерживает ли Google App Engine JOIN, чтобы избежать проблемы N + 1 select .
Google App Engine не поддерживает JOIN напрямую, но позволяет вам определить one to many relationship, используя ReferenceProperty .

class Author(db.Model):
  name = db.StringProperty()

class Book(db.Model):
  title = db.StringProperty()
  author= db.ReferenceProperty(Author)

В вашем конкретном сценарии с двумя запросами запросов первый должен получить автора:

author = Author.all.filter('name =' , 'fooauthor').get()

, а второй - найтивсе книги данного автора:

books = Book.all().filter('author=', author).fetch(...)

вы можете получить тот же результат общего SQL-запроса, который использует JOIN.

Проблема N + 1 можетнапример, появляются, когда мы хотим получить 100 книг, каждая с именем автора:

books = Book.all().fetch(100)
for book in books:
    print book.author.name

В этом случае нам нужно выполнить 1 + 100 запросов, один для получения списка книг и 100 для разыменования всехавторы возражают, чтобы получить имя автора (этот шаг неявно выполняется в операторе book.author.name).

Один из распространенных методов решения этой проблемы - использование метода get_value_for_datastore, который возвращает ключ указанного автора для данного объекта.книга без дессылка на него (т. е. выборка из хранилища данных):

author_key = Book.author.get_value_for_datastore(book)

В этой теме есть блестящее сообщение в блоге , которое вы можете прочитать.
Этот метод, начиная с author_key список, предварительно выбирает объекты авторов из хранилища данных, устанавливая каждый из них в соответствующую книгу сущностей.
При таком подходе экономится много обращений к хранилищу данных, и практически * избегает N + 1 проблема.

* теоретически, на книжной полке со 100 книгами, написанными 100 разными авторами, нам все равно придется вызывать хранилище данных 100 + 1 раз

Отвечая на вашвопрос:

  • Google App Engine не поддерживает нетерпеливое извлечение
  • Существуют методы (не из коробки), которые помогают избежать страшных N + 1 задача
...