2

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

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

ответ

3

Я думаю, что вы неявно спрашиваете, поддерживает ли 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) 

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

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

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

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

Отлично, спасибо! Есть ли «ReferenceProperty» для Java? –

+0

@Jen посмотреть [здесь] (http://code.google.com/intl/it-IT/appengine/docs/java/datastore/relationships.html#Owned_One_to_Many_Relationships) – systempuntoout

Смежные вопросы