Проектирование баз данных - механизм приложения Google

Я работаю с механизмом приложения Google и использую низкий уровень API Java для доступа к Большой Таблице. Я создаю приложение SaaS с 4 слоями:

  • Клиентский веб-браузер
  • УСПОКОИТЕЛЬНЫЙ слой ресурсов
  • Бизнес-слой
  • Уровень доступа к данным

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

  • Назначения
  • Позиции
  • Счета
  • Платежи

Назначение: "Назначение" является местом и время, где сотрудники, как ожидают, будут в порядке для предоставления услуги.

Позиция: "Позиция" является сервисом, сбором или скидкой и ее связанной информацией. Пример позиций, которые могли бы войти в назначение:

Name:                          Price: Commission: Time estimate   
Full Detail, Regular Size:        160       75       3.5 hours 
$10 Off Full Detail Coupon:       -10        0         0 hours 
Premium Detail:                   220      110       4.5 hours 
Derived totals(not a line item): $370     $185       8.0 hours

Счет: "Счет" является записью одной или нескольких позиций, которые клиент передал для оплаты за.

Оплата: "Оплата" является записью того, какие платежи вошли.

В предыдущей реализации этого приложения жизнь была более простой, и я рассматривал все четыре из этих понятий как одна таблица в базе данных SQL: "Назначение". Одно "Назначение" могло иметь несколько позиций, несколько платежей и один счет. Счет был просто электронным письмом, или распечатайте, который был произведен из клиентской записи и позиций.

9 из 10 раз, это хорошо работало. Когда один клиент назначил одну встречу для один или несколько механизмов и заплатил за нее самих, все было главным. Но эта система не работала при большом количестве условий. Например:

  • То, когда один клиент назначил одну встречу, но назначение стало отмененным из-за дождя на полпути посредством приведения к чертежнику-конструктору, должно было возвратиться на следующий день, мне были нужны два назначения, но только одна позиция, один счет и одна оплата.
  • Когда группа клиентов в офисе, все решили иметь их автомобили, сделанные тот же день для получения скидки, мне были нужны одно назначение, но несколько счетов и несколько платежей.
  • Когда один клиент заплатил за две встречи с одной проверкой, мне были нужны два назначения, но только один счет и одна оплата.

Я смог обработать все эти выбросы путем уклонения от вещей немного. Например, если бы чертежник-конструктор должен был возвратиться на следующий день, то я просто назначил бы другую встречу во второй день с позицией, которая, поскольку, который сказал, "Заканчиваются" и стоимость составила бы 0$. Или если я сделал, чтобы один клиент заплатил за две встречи с одной проверкой, я поместил платежные записи разделения в каждое назначение. Проблема с этим состоит в том, что это создает огромную возможность для данных в соответствии. Данные в соответствии могут быть серьезной проблемой специально для случаев, включающих финансовую информацию, таких как третий экс-клен где клиент, оплаченный две встречи с одной проверкой. Платежи должны подойтись непосредственно с товарами и услугами, представленными для надлежащего отслеживания дебиторскую задолженность.

Предложенная структура:

Ниже, нормализованная структура для того, чтобы организовать и хранить эти данные. Возможно, из-за моей неопытности, я делаю большой акцент на нормализацию данных, потому что это походит на отличный способ избежать ошибок несовместимости данных. С этой структурой изменения в данных могут быть сделаны с одной операцией, не имея необходимость волноваться об обновлении других таблиц. Чтения, однако, могут потребовать нескольких чтений вместе с организацией в оперативной памяти данных. Я фигурирую позже, если существуют проблемы производительности, я могу добавить некоторые денормализованные поля к "Назначению" для более быстрых запросов при сохранении "безопасной" нормализованной структуры в целости. Денормализация могла потенциально замедлить записи, но я думал, что смог выполнять асинхронные вызовы к другим ресурсам или добавлять к задаче que так, чтобы клиент не ожидал дополнительных записей, которые обновляют денормализованные части данных.

Таблицы:

Appointment
 start_time
 etc...

Invoice
 due_date
 etc...

Payment
 invoice_Key_List
 amount_paid
 etc...

Line_Item
 appointment_Key_List
 invoice_Key
 name
 price
 etc...

Следующее является серией запросов и операций, требуемых связывать все четыре объекта (таблицы) вместе для данного списка назначений. Это включало бы информацию о том, какие сервисы были запланированы для каждого назначения, общей стоимости каждого назначения и погоды или не оплата, как получено для каждого назначения. Это было бы общим запросом при загрузке календаря для планирования назначения или чтобы менеджер получил полное представление операций.

  • ЗАПРОС для списка "Назначений", кто "start_time" поле, находится между данным диапазоном.
    • Добавьте каждый ключ от возвращенных назначений в Список.
  • ЗАПРОС для всего "Line_Items", кто appointment_key_List поле, включает любое из назначений возвратов
    • Добавьте каждый invoice_key от всех позиций в набор Набора.
  • ЗАПРОС для всех "Счетов" в наборе кета счета (это может быть сделано в одной асинхронной операции с помощью механизма приложения),
    • Добавьте каждый ключ из возвращенных счетов в Список
  • ЗАПРОС для всех "Платежей", кто invoice_key_list поле, содержит ключ, соответствующий любому из возвращенных счетов
  • Реорганизуйте в памяти так, чтобы каждое назначение отразило line_items, которые планируются для него, общая стоимость, общее предполагаемое время и погода, или не это оплатили.

... Как Вы видите, эта операция требует 4 запросов хранилища данных, а также некоторой организации в оперативной памяти (надо надеяться, в оперативной памяти будет довольно быстро),

Кто-либо может прокомментировать этот дизайн? Это является лучшим, я мог придумать, но я подозреваю, что могли бы быть более оптимальные варианты или совершенно другие проекты, о которых я не думаю, который мог бы работать лучше в целом или конкретно под GAE's (механизм приложения Google) преимущества, слабые места и возможности.

Спасибо!

Разъяснение использования

Большинство приложений более интенсивно чтением, некоторые - больше интенсивной записи. Ниже, я описываю типичный пример использования и ломаю операции, которые пользователь хотел бы выполнить:

Менеджер получает вызов от клиента:

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

Менеджер делает исходящий телефонный вызов:

  • Читайте менеджер загружает календарь
  • Читайте менеджер загружает назначение для клиента, которого он хочет позвонить
  • Запишите, что менеджер нажимает кнопку "Call", вызов инициируется, и новый объект CallReacord записан
  • Читайте Сервер вызовов отвечает на запрос вызова и читает CallRecord, чтобы узнать, как обработать вызов
  • Запишите записям Сервера вызовов обновленную информацию в CallRecord
  • Запишите, когда вызов закрывается, сервер вызовов выполняет другой запрос к серверу для обновления ресурса CallRecord (примечание: этот запрос не строго ограничен во времени),

Принятый ответ:: Оба из лучших двух ответов были очень вдумчивыми и ценились. Я принял тот с немногими голосами для несовершенной компенсации их воздействия как можно больше.

7
задан Chris Dutrow 29 June 2010 в 21:47
поделиться

3 ответа

Вы указали два конкретных «просмотра», которые должен предоставить ваш веб-сайт:

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

  2. Общий вид операций. Я не совсем уверен, что это влечет за собой, но если вам нужно выполнить строку из четырех запросов, о которых вы упомянули выше, чтобы получить это, то ваш дизайн можно было бы улучшить. Подробности ниже.

Четыре запроса к хранилищу данных сами по себе не обязательно являются чрезмерными. Проблема в вашем случае в том, что два запроса являются дорогостоящими и, вероятно, даже невозможными . Я рассмотрю каждый вопрос:

  1. Получить список встреч - нет проблем. Этот запрос сможет сканировать индекс, чтобы эффективно получать встречи в указанном вами диапазоне дат.

  2. Получить все позиции для каждой встречи из №1 - это проблема. Этот запрос требует выполнения запроса IN .Запросы IN преобразуются в N подзапросов за кулисами - так что вы получите один запрос для каждого ключа встречи из №1! Они будут выполняться параллельно, так что это не так уж плохо. Основная проблема заключается в том, что запросы IN ограничены только небольшим списком значений (до 30 значений). Если у вас более 30 ключей встречи, возвращенных # 1, то этот запрос не будет выполнен!

  3. Получить все счета-фактуры, на которые есть ссылки по позициям - нет проблем. Вы правы, что этот запрос дешевый, потому что вы можете просто получить все соответствующие счета напрямую по ключу. (Примечание: этот запрос все еще синхронный - я не думаю, что асинхронный - это то слово, которое вы искали).

  4. Получить все платежи по всем счетам, возвращенным №3 - это проблема. Как и №2, этот запрос будет запросом IN и завершится ошибкой, если №3 вернет даже небольшое количество счетов-фактур, по которым вам нужно получить платежи.

Если количество элементов, возвращаемых # 1 и # 3, достаточно мало, то GAE почти наверняка сможет сделать это в допустимых пределах. И этого должно быть достаточно для ваших личных нужд - похоже, что он вам в основном нужен для работы, и не нужно его масштабировать для огромного количества пользователей (это не так).

Предложения по улучшению:

  • Денормализация! Попробуйте сохранить ключи для сущностей Line_Item , Invoice и Payment , относящихся к данной встрече, в списках на самой встрече. Затем вы можете исключить свои запросы IN .Убедитесь, что эти новые ListProperty не проиндексированы, чтобы избежать проблем с увеличивающимися индексами

Другие, менее конкретные идеи для улучшения:

  • В зависимости от вашего «общего видения» операции ", вы можете разделить получение всей этой информации. Например, возможно, вы начинаете с отображения списка встреч, а затем, когда менеджеру требуется дополнительная информация о конкретной встрече, вы переходите и получаете информацию, относящуюся к этой встрече. Вы даже можете сделать это через AJAX, если это взаимодействие будет происходить на одной странице.
  • Memcache - ваш друг - используйте его для кеширования результатов запросов к хранилищу данных (или даже результатов более высокого уровня), чтобы вам не приходилось пересчитывать его с нуля при каждом доступе.
9
ответ дан 6 December 2019 в 10:47
поделиться

Вот несколько факторов, специфичных для движка приложения, которые, я думаю, вы приходится иметь дело с:

  • При запросе с использованием неравенства вы можете использовать неравенство только для одного свойства . например, если вы фильтруете дату приложения между 1 и 4 июля, вы также не можете фильтровать по цене> 200

  • Транзакции в движке приложения немного сложнее по сравнению с базой данных SQL, которую вы используете наверное привык. Вы можете выполнять транзакции только с объектами, которые находятся в одной « группе объектов ».

2
ответ дан 6 December 2019 в 10:47
поделиться

Как вы заметили, этот дизайн не масштабируется. Для рендеринга страницы требуется 4 (!!!) запроса к БД. Это на 3 штуки слишком много :)

Преобладающее представление о работе с App Engine Datastore состоит в том, что вы хотите выполнять как можно больше работы, когда что-то написано, так что почти ничего не нужно делать, когда что-то извлекается и оказано. Предположительно, вы записываете данные очень мало раз по сравнению с тем, сколько раз они отображались.

Нормализация - это то же самое, к чему вы, кажется, стремитесь.Хранилище данных не придает значения нормализации - это может означать меньшее несоответствие данных, но это также означает, что чтение данных происходит намного медленнее (4 чтения? !!). Поскольку ваши данные читаются гораздо чаще, чем записываются, оптимизируйте чтение, даже если это означает, что ваши данные будут время от времени дублироваться или не синхронизироваться в течение короткого промежутка времени.

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

Так как вам следует оптимизировать чтение, часто ваши записи вырастут до гигантских размеров. Настолько гигантский, что вы не можете уместить его в 30-секундный лимит времени для запросов. Вот для чего предназначена очередь задач . Сохраните то, что вы считаете «самым необходимым» вашей модели в хранилище данных, затем запустите очередь задач, чтобы вытащить ее обратно, сгенерировать HTML-код для визуализации и поместить его туда в фоновом режиме. Это может означать, что ваша модель немедленно готова к отображению до тех пор, пока задача не завершится с ней, поэтому в этом случае вам понадобится постепенная деградация, даже если это означает отрисовку ее «медленным способом» до тех пор, пока данные не будут полностью заполнены. Любые дальнейшие чтения будут молниеносными.

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

Я могу дать вам несколько ссылок на несколько очень полезных видеороликов о хранилище данных:

  • Бретт Слаткин 2008 и 2009 рассказывает о создании масштабируемых , сложные приложения на App Engine и отличное приложение из в этом году о конвейерах данных (что, я думаю, не имеет прямого отношения, но действительно полезно в целом)
  • App Engine Under the Covers : Как App Engine делает то, что делает, за кулисами
  • AppStats : отличный способ узнать, сколько операций чтения из хранилища данных вы выполняете, и несколько советов по уменьшению этого числа
7
ответ дан 6 December 2019 в 10:47
поделиться
Другие вопросы по тегам:

Похожие вопросы: