Поддерживает ли хранилище данных GAE немедленную выборку?

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

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


person Tony the Pony    schedule 11.11.2010    source источник


Ответы (1)


Я думаю, вы косвенно спрашиваете, поддерживает ли Google App Engine JOIN, чтобы избежать проблемы выбора N+1.
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.
person systempuntoout    schedule 11.11.2010