Я работаю с механизмом приложения 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...
Следующее является серией запросов и операций, требуемых связывать все четыре объекта (таблицы) вместе для данного списка назначений. Это включало бы информацию о том, какие сервисы были запланированы для каждого назначения, общей стоимости каждого назначения и погоды или не оплата, как получено для каждого назначения. Это было бы общим запросом при загрузке календаря для планирования назначения или чтобы менеджер получил полное представление операций.
... Как Вы видите, эта операция требует 4 запросов хранилища данных, а также некоторой организации в оперативной памяти (надо надеяться, в оперативной памяти будет довольно быстро),
Кто-либо может прокомментировать этот дизайн? Это является лучшим, я мог придумать, но я подозреваю, что могли бы быть более оптимальные варианты или совершенно другие проекты, о которых я не думаю, который мог бы работать лучше в целом или конкретно под GAE's (механизм приложения Google) преимущества, слабые места и возможности.
Спасибо!
Большинство приложений более интенсивно чтением, некоторые - больше интенсивной записи. Ниже, я описываю типичный пример использования и ломаю операции, которые пользователь хотел бы выполнить:
Менеджер получает вызов от клиента:
Менеджер делает исходящий телефонный вызов:
Принятый ответ:: Оба из лучших двух ответов были очень вдумчивыми и ценились. Я принял тот с немногими голосами для несовершенной компенсации их воздействия как можно больше.
Вы указали два конкретных «просмотра», которые должен предоставить ваш веб-сайт:
Назначение встречи. Ваша текущая схема должна отлично работать для этого - вам просто нужно выполнить первый запрос, который вы упомянули.
Общий вид операций. Я не совсем уверен, что это влечет за собой, но если вам нужно выполнить строку из четырех запросов, о которых вы упомянули выше, чтобы получить это, то ваш дизайн можно было бы улучшить. Подробности ниже.
Четыре запроса к хранилищу данных сами по себе не обязательно являются чрезмерными. Проблема в вашем случае в том, что два запроса являются дорогостоящими и, вероятно, даже невозможными . Я рассмотрю каждый вопрос:
Получить список встреч - нет проблем. Этот запрос сможет сканировать индекс, чтобы эффективно получать встречи в указанном вами диапазоне дат.
Получить все позиции для каждой встречи из №1 - это проблема. Этот запрос требует выполнения запроса IN
.Запросы IN
преобразуются в N
подзапросов за кулисами - так что вы получите один запрос для каждого ключа встречи из №1! Они будут выполняться параллельно, так что это не так уж плохо. Основная проблема заключается в том, что запросы IN
ограничены только небольшим списком значений (до 30 значений). Если у вас более 30 ключей встречи, возвращенных # 1, то этот запрос не будет выполнен!
Получить все счета-фактуры, на которые есть ссылки по позициям - нет проблем. Вы правы, что этот запрос дешевый, потому что вы можете просто получить все соответствующие счета напрямую по ключу. (Примечание: этот запрос все еще синхронный - я не думаю, что асинхронный - это то слово, которое вы искали).
Получить все платежи по всем счетам, возвращенным №3 - это проблема. Как и №2, этот запрос будет запросом IN
и завершится ошибкой, если №3 вернет даже небольшое количество счетов-фактур, по которым вам нужно получить платежи.
Если количество элементов, возвращаемых # 1 и # 3, достаточно мало, то GAE почти наверняка сможет сделать это в допустимых пределах. И этого должно быть достаточно для ваших личных нужд - похоже, что он вам в основном нужен для работы, и не нужно его масштабировать для огромного количества пользователей (это не так).
Предложения по улучшению:
Line_Item
, Invoice
и Payment
, относящихся к данной встрече, в списках на самой встрече. Затем вы можете исключить свои запросы IN
.Убедитесь, что эти новые ListProperty
не проиндексированы, чтобы избежать проблем с увеличивающимися индексами Другие, менее конкретные идеи для улучшения:
Вот несколько факторов, специфичных для движка приложения, которые, я думаю, вы приходится иметь дело с:
При запросе с использованием неравенства вы можете использовать неравенство только для одного свойства . например, если вы фильтруете дату приложения между 1 и 4 июля, вы также не можете фильтровать по цене> 200
Транзакции в движке приложения немного сложнее по сравнению с базой данных SQL, которую вы используете наверное привык. Вы можете выполнять транзакции только с объектами, которые находятся в одной « группе объектов ».
Как вы заметили, этот дизайн не масштабируется. Для рендеринга страницы требуется 4 (!!!) запроса к БД. Это на 3 штуки слишком много :)
Преобладающее представление о работе с App Engine Datastore состоит в том, что вы хотите выполнять как можно больше работы, когда что-то написано, так что почти ничего не нужно делать, когда что-то извлекается и оказано. Предположительно, вы записываете данные очень мало раз по сравнению с тем, сколько раз они отображались.
Нормализация - это то же самое, к чему вы, кажется, стремитесь.Хранилище данных не придает значения нормализации - это может означать меньшее несоответствие данных, но это также означает, что чтение данных происходит намного медленнее (4 чтения? !!). Поскольку ваши данные читаются гораздо чаще, чем записываются, оптимизируйте чтение, даже если это означает, что ваши данные будут время от времени дублироваться или не синхронизироваться в течение короткого промежутка времени.
Вместо того чтобы думать о том, как данные выглядят при хранении, подумайте о том, как вы хотите, чтобы данные выглядели, когда они отображаются для пользователя. Храните как можно ближе к этому формату, даже если это означает буквально сохранение предварительно обработанного HTML в хранилище данных. Чтение будет молниеносным, и это хорошо.
Так как вам следует оптимизировать чтение, часто ваши записи вырастут до гигантских размеров. Настолько гигантский, что вы не можете уместить его в 30-секундный лимит времени для запросов. Вот для чего предназначена очередь задач . Сохраните то, что вы считаете «самым необходимым» вашей модели в хранилище данных, затем запустите очередь задач, чтобы вытащить ее обратно, сгенерировать HTML-код для визуализации и поместить его туда в фоновом режиме. Это может означать, что ваша модель немедленно готова к отображению до тех пор, пока задача не завершится с ней, поэтому в этом случае вам понадобится постепенная деградация, даже если это означает отрисовку ее «медленным способом» до тех пор, пока данные не будут полностью заполнены. Любые дальнейшие чтения будут молниеносными.
Таким образом, у меня нет никаких конкретных советов, напрямую связанных с вашей базой данных - это зависит от того, как вы хотите, чтобы данные выглядели, когда пользователь их видит.
Я могу дать вам несколько ссылок на несколько очень полезных видеороликов о хранилище данных: