2010-04-12 30 views
7

背景
我正在写一个调查,这将是一个很大的观众。它包含15个问题,每个问题有五个可能的答案以及潜在的评论。如果我需要将数据库上的流量降到最低,那么存储问卷和调查答案的最佳方式是什么?

用户可以在所有15个问题中按任意顺序回答问题,并可以随时离开问卷调查并回答问题。

一旦在所有15个问题上尝试了答案,就会出现一个提交按钮,允许他们将问题提交为最终答案。在该阶段之前,只要用户加载调查页面,就需要可检索所有答案。

要求是用户只能看到一个页面上的一个问题,'上一个'和'下一个'按钮允许用户滚动浏览问题。

要求
我可以在用户每次点击一个按钮时要求的问题,并保存当前的响应等等,但是这将是一个大量结果到已经大量使用的数据库。我没有时间去购买一台新的服务器等,所以我不得不与我有什么关系。有什么办法可以缓存用户机器和/或响应的问题吗?很明显,我需要响应数据是安全的,只有用户知道,所以我觉得这样做的最佳方式有点卡住了。任何指针?

如果这意味着我会得到一些高质量的讨论和反馈,我准备在这个问题上提供100分的奖励。

+1

为什么你需要最小化数据库访问?性能?如果设计得当,这看起来不应该是数据库密集型的。 – 2010-04-13 01:14:13

+0

您是否在意扩大罗曼? – 2010-04-15 08:55:26

回答

1

您有需要平衡三个方面的要求:

  • 用户必须能够在任何时候通过用户输入的
  • 答案必须用数据损失尽可能少的机会被保存回到自己的调查
  • 需要尽量减少数据库的访问

涉及在不稳定的地方(Cookie,会话等)的缓存回答任何解决方案都会增加数据丢失的风险。最终的解决方案取决于您如何对重要性的三个要求进行排名。如果数据库问题位于顶部,那么您需要承担数据丢失的风险,或者使用一些临时存储方案(例如Kevin的平面文件构思)花费大量额外时间来编写解决方案。

几个人的建议,你可能会过早地优化。我建议你首先考虑这个想法 - 也许这整个事情是没有意义的。

但是,假设你的数据库情况是一个真正的问题,我认为你的需求最好的平衡将是一个系统,立即保存数据库的答案(以防止数据丢失),但仔细管理,当你实际上必须击中D b。

  1. 当应用程序启动时(或第一个用户请求调查时)将调查及其问题加载到应用程序缓存中。如果任何问题有可能的答案的选择列表,也加载这些。您只需在应用程序生命周期(或缓存持续时间)内打一次数据库即可加载调查数据。
  2. 当用户开始他们的调查时,运行单个查询以将任何现有答案(如果他们是回访用户)加载到会话中的对象中 - 可以像<List>string那样简单。 (如果您可以以某种方式识别新用户而不必击中数据库,那么您可以跳过此步骤以供新用户使用。)
  3. 在会话缓存中使用会话应答对象以及调查问题对象来填充每个页面而不点击再次分贝。
  4. 当用户提交答案时,将其与会话答案对象进行比较,以查看它是否发生了变化(她可能只是单击带有先前输入的答案的页面上的“下一个”)。如果答案是新的或已更改,则将其保存到数据库和会话答案对象。
  5. 当用户离开调查时,您无需执行任何操作 - 所有内容都已保存。

通过这个方案,您可以打一次数据库来加载调查,当每个用户开始(或重新启动)调查时为每个用户加一次调查,并为每个新的或修改后的答案添加一次。可能没有你期望的那么大,但是它为你提供了最好的数据保护。

1

如果数据库旅行是一个问题,您可以缓存他们在Web服务器(或任何应用程序所在),但它听起来好像需要记录每个答案的用户进入到下一个问题。

如果每个人的问题和可能的答案都是相同的,我肯定会将它们缓存在应用程序层 - 这可以存储在Application对象中。无论如何,您当然可以优化数据库调用以尽可能高效地返回结果 - 即多个结果集或来自单个存储过程的联合结果集。如果您不介意每个会话有多个Copes(或者如果有变化),则可以将其存储在Session对象中。将它存储在客户端(即一个cookie)并不真正安全,并且可以保持Web服务器 - 客户端带宽的节省。尽管如此,这听起来像很不成熟的优化。

+0

我并不认为带宽是一个问题。关注似乎是重创数据库 – 2010-04-12 19:34:21

+0

@David我不知道为什么缓存它在客户端比Web /应用程序服务器更好。 – 2010-04-12 19:37:54

+0

只要流量不在数据库(SQL Server)上,我就可以对应用服务器上的缓存提出建议,那么这就是赢家。 – 2010-04-12 19:41:17

0

你的意思是一个饼干?

+0

安全是必须的 - 我如何确保cookie的安全? – 2010-04-12 19:41:54

+1

加密。加密cookie的内容。 – aepheus 2010-04-12 19:53:47

+0

我对Safari有过不好的体验,并更改了cookie值。即使是现在的版本。如果您必须支持该浏览器,请注意一些事项。 – NotMe 2010-04-13 16:53:45

1

这是一个经典的问题做一个基于浏览器的系统页面之间保持状态。我还假设,即使用户注销并稍后回来,我们也希望这些数据持续存在。下面是选项:

  • 具备高可用性的服务器,我们可以保持在内存中(不会话)15个回答单个集合为此用户(可能不是一个好主意,不容易负载平衡)
  • 我们denormalise 15个答案为1行中的SQL表
  • 我们坚持使用Cookie或localStorage的(IE8)客户端上的数据。

我的感觉是,前两个选项可能不是你要找的,所以让我们来探索最后一个选项。

你可以很简单地将答案存储在cookie中。这很可能会丢失,并且用户可能从另一台机器登录,但这可能是一个可接受的风险。使用支持HTML5的最新浏览器(包括IE8 afaik),您可以获得localStorage的好处,而不像Cookie那样轻松删除。如果这不可用,你可以回到cookie。

如果需要,可以对cookie进行加密。

1

不确定您正在使用的语言等,但大多数都有应用程序缓存。我会将问题存储在那里,并从数据库中检索它们,并在它们不在缓存中时将其存储(应用程序回收时)。

至于答案,用户是否登录了一些如何?在所有问题得到解答之前,将答案保存在cookie中是否可行?

编辑: 如果cookie不够可靠,您可以在应用程序缓存中存储要执行的查询列表(插入/更新),直到达到查询限制时才会执行它们,或者在某些条件下(即当用户请求列表中的答案时执行查询列表,应用程序回收时执行列表等)。

相当粗糙,但你的想法:

if (function == "get question" && userQuestionIsInQueue) || function == "finish survey" 
execute(Application["querylist"]); 
continue as normal... 

if function == "submit answer" 
if Application["querylist"] == null 
Application["querylist"] = newAnswerQuery; 
else 
Application["querylist"] += newAnswerQuery; 

还就需要(应用[“querylist”])添加到执行回收事件,我相信你可以在全局钩子它.asax

编辑2: 我也会将一个请求的所有数据库事务累加到1中,如果您确实必须执行清单,然后为用户获取答案,请在同一事务中执行并保存行程。优化时的常用做法。

+0

我使用ASP.NET这就是为什么我标记它。我还标记了VB.Net和C#,但Adam删除了这些。我对编码感到满意,因为原理是一样的。 – 2010-04-12 19:37:56

+0

感谢编辑 - 这听起来很有趣,你有这样的技术的例子吗? – 2010-04-12 19:42:51

+0

应用[“my_questions”] =问题; – aepheus 2010-04-12 19:43:08

2

除非有使用数据库的原因,否则您可以始终将结果存储在服务器本身的平面文件中。这听起来不像你存储的数据是以任何方式关系的。最糟糕的是,你总是可以将它们作为批处理作业插入到关系数据库中。

另一种选择是应用程序缓存。但是,如果您的Web服务器突然崩溃,则可能会丢失此处的信息。

您还可以将值存储在用户的Cookie中。

1

您的场景是Predictive Fetch Pattern的完美人选。我建议你缓存所有问题。当用户登录使用该模式来获取前5个答案(如果他们已经给出了答案)并且基于他们的导航(他们当前的问题在哪里)从Response对象或从DB获取信息。

HTH

1

我想向你提供这就是所谓的Dom存储,但因为只有新的浏览器都支持它,它可以使用它在这一点上有问题HTML5的新特性。

使用DOM存储,您可以将数据存储在用户浏览器中。由于它可以在Mozilla Firefox [3],Google Chrome和Opera中为每个域存储高达5MB的Internet Explorer中的每个存储区10MB,因此您可以在DOM存储中存储答案和问题ID。

即使DOM存储,更不用说数据库命中,就可以降低服务器打为好。

因为我们都知道使用cookie的工作是麻烦有时,它可以存储4KB,最简单的方法,现在存储键值信息在DOM存储是。

您可以为会议以及本地存储具体键值信息。会话结束时,基于会话的信息将从浏览器中清除,但如果存储基于本地的值,则即使用户关闭了该选项卡,键值也会保留一段时间。

示例代码:

<p> 
    You have viewed this page 
    <span id="count">an untold number of</span> 
    time(s). 
</p> 
<script> 
    var storage = window.localStorage; 
    if (!storage.pageLoadCount) storage.pageLoadCount = 0; 
    storage.pageLoadCount = parseInt(storage.pageLoadCount, 10) + 1; 
    document.getElementById('count').innerHTML = storage.pageLoadCount; 
</script> 

您可以了解更多有关DOM存储从下面的链接:

2

根据我个人的经验(每秒提供数千个简短的调查页面),我怀疑你的担心是没有根据的。除其他原因之外,DBMS会将您可以更有效地缓存这些少量数据。

我测试过这一点,加载问题和答案为应用程序范围收集在启动时,之后,从内存中为他们服务的 - 经常是没有区别的。

你的选择是一次发送给所有的浏览器,并将其保存为JavaScript应用程序,存储的数据(加密),饼干和只命中数据库时,整个事情是完成的。这是乏味但不难。

相关问题