Chr*_*row 7 google-app-engine database-design bigtable appointment
我正在使用谷歌应用引擎并使用低leval java api访问Big Table.我正在构建一个包含4层的SAAS应用程序:
我正在构建一个应用程序来帮助管理我的移动汽车细节公司(以及其他类似的公司).我必须代表这四个独立的概念,但不确定我目前的计划是否合适:
预约: "预约"是指员工需要提供服务的地点和时间.
订单项: "订单项"是服务,费用或折扣及其相关信息.可能进入约会的订单项示例:
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数据库中的一个表:"约会".一个"约会"可以有多个订单项,多笔付款和一张发票.发票只是通过订单项和客户记录生成的电子邮件或打印件.
十分之九,这很好.当一个客户预约一辆或几辆车并自己付款时,一切都很棒.但是这个系统在很多条件下都不起作用.例如:
通过稍微捏造一些东西,我能够处理所有这些异常值.例如,如果细节设计者必须在第二天回来,我会在第二天再次预约,其中的一个项目表示"完成",费用为0美元.或者,如果我有一个客户通过一张支票支付两次预约的费用,我会在每次预约中分配支付记录.这样做的问题在于它为数据一致性创造了巨大的机会.数据一致性可能是一个严重的问题,尤其是涉及财务信息的案例,例如客户通过一张支票支付两次约会的第三个例子.付款必须与提供的商品和服务直接匹配,以便正确跟踪应收账款.
下面是用于组织和存储该数据的标准化结构.也许是因为我缺乏经验,我非常重视数据规范化,因为它似乎是避免数据不一致错误的好方法.使用这种结构,可以通过一次操作完成对数据的更改,而无需担心更新其他表.但是,读取可能需要多次读取以及内存中的数据组织.我稍后会想到,如果存在性能问题,我可以在"约会"中添加一些非规范化字段,以便更快地查询,同时保持"安全"规范化结构的完整性.非规范化可能会减慢写入速度,
表:
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...
Run Code Online (Sandbox Code Playgroud)
以下是将给定的约会列表将所有四个实体(表)绑定在一起所需的一系列查询和操作.这将包括有关每次预约安排了哪些服务的信息,每次预约的总费用以及每次预约收到的天气或不付款.当加载日历以进行约会安排或管理者获得操作的整体视图时,这将是一个常见的查询.
...正如您所看到的,此操作需要4个数据存储区查询以及一些内存组织(希望内存中的速度非常快)
任何人都可以评论这个设计吗?这是我能想到的最好的,但我怀疑可能有更好的选择或完全不同的设计,我没想到它可能在一般情况下更好或者特别是在GAE(谷歌应用程序引擎)的优势,劣势和能力下.
谢谢!
大多数应用程序更加读取密集型,有些应用程序更加密集.下面,我将描述用户想要执行的典型用例和细分操作:
经理接到客户的电话:
经理拨打电话:
接受的答案:: 前两个答案都非常周到和赞赏.为了尽可能不完美地平衡他们的曝光率,我接受了投票少的人.
您指定了网站需要提供的两个特定"视图":
安排预约.您当前的方案应该可以正常工作 - 您只需要执行您提到的第一个查询.
整体运营观点.我不确定这会带来什么,但如果您需要执行上面提到的四个查询字符串来获得此信息,那么您的设计可能会使用一些改进.详情如下.
四个数据存储区查询本身并不一定是过分的.在你的情况下,问题是两个查询是昂贵的,甚至可能是不可能的.我将通过每个查询:
获取约会列表 - 没问题.此查询将能够扫描索引以有效地检索您指定的日期范围内的约会.
获取#1中每个约会的所有订单项 - 这是一个问题.此查询要求您执行IN查询. IN查询会N在幕后转换为子查询 - 因此您最终会从#1的每个约会密钥中获得一个查询!这些将并行执行,因此不是那么糟糕.主要问题是IN查询仅限于一小部分值(最多只有30个值).如果#1返回的约会密钥超过30个,则此查询将无法执行!
获取订单项引用的所有发票 - 没问题.你这个查询很便宜是正确的,因为你可以直接通过密钥获取所有相关的发票.(注意:此查询仍然是同步的 - 我不认为异步是您正在寻找的单词).
获取#3返回的所有发票的所有付款 - 这是一个问题.与#2一样,此查询将是一个IN查询,如果#3返回您需要获取付款的中等数量的发票,则该查询将失败.
如果#1和#3返回的项目数量足够小,那么GAE几乎肯定能够在允许的限制范围内执行此操作.这应该足以满足您的个人需求 - 听起来您最需要它才能工作,并且不需要扩展到大量用户(它不会).
改进建议:
Line_Item,Invoice以及Payment相关的名单上任命本身就是一个给定的约会实体.然后,您可以消除您的IN查询.确保这些新ListProperty的没有索引,以避免问题的爆发指数其他不太具体的改进想法:
正如您所注意到的,此设计无法扩展.它需要4(!!!)DB查询来呈现页面.这太多了:)
使用App Engine数据存储区的主流概念是,您希望在编写内容时尽可能多地完成工作,这样在检索和呈现内容时几乎不需要执行任何操作.大概数次写入数据,与渲染的次数相比.
规范化同样是你似乎正在努力的事情.数据存储区在归一化中没有任何价值 - 它可能意味着数据不一致,但这也意味着读取数据的速度会慢得多(4次读取?!!).由于您的数据读取的频率比写入的频率高得多,因此优化读取,即使这意味着您的数据偶尔会被复制或不同步.
不要考虑数据在存储时的外观,而是考虑数据在向用户显示时的外观.尽可能接近该格式存储,即使这意味着在数据存储区中存储预呈现的HTML.读取将是闪电般的,这是一件好事.
因此,既然您应该优化读取,那么您的写入通常会增长到巨大的比例.如此巨大,以至于您无法在30秒的时间限制内完成请求.那就是任务队列的用途.将您认为模型的"必需品"存储在数据存储区中,然后触发任务队列将其拉出,生成要呈现的HTML,并将其放在后台.这可能意味着您的模型可以立即显示,直到任务完成,因此在这种情况下您需要优雅降级,即使这意味着在数据完全填充之前将其呈现为"缓慢的方式".任何进一步的读取都会很快.
总之,我没有任何与您的数据库直接相关的具体建议 - 这取决于您希望数据在用户看到时的样子.
我可以给你一些链接到有关数据存储的一些超级有用的视频:
| 归档时间: |
|
| 查看次数: |
2207 次 |
| 最近记录: |