这种去规范化是否有意义?

时间:2013-10-24 20:09:57

标签: mysql sql performance http web

我有2张桌子,我经常加入。为了简化这一点,联接会返回一系列ID,我在另一个(复杂)查询中使用这些ID作为IN的一部分。
所以我一直这样加入以获取特定ID。

要清楚,查询速度并不是非常慢。大约需要2分钟。但是,由于我通过网页调用此查询,因此延迟很明显。

作为一个具体的例子,假设我加入的表是供应商表和包含供应商配备特定日期的仓库的表。基本上,我获得了在特定日期为特定仓库提供服务的供应商的ID。

它本身的查询无法改进,因为它是两个被索引的表之间的简单连接,但由于存在日期范围,这使事情变得复杂。

我有以下想法,我不确定它是否有意义。
由于我查询的数据(特别是以前的日期)不会改变,如果我创建了另一个具有主键的表,我的where中的列以及ID列表(逗号分隔)的值。 这样它就是1行的简单选择 即这样我就可以“预存”我需要的供应商ID 我知道这甚至不是第一次正常的形式,但它有意义吗?还有另一种方法吗?

2 个答案:

答案 0 :(得分:1)

作为非规范化设计,它可以加速你所拥有的特定类型的查询。

虽然如果您的日期范围发生变化,但是它不能导致一组不同的ID吗?

另一种方法是真正将非规范化条目视为密钥/值缓存中的条目,如memcached或redis。将实际数据存储在规范化表中,并定期更新缓存的非规范化表单。


重新评论:

是的,通常在字符串中存储id列表是针对关系数据库设计的。请参阅我对Is storing a delimited list in a database column really that bad?

的回答

但另一方面,在某些情况下,非规范化是合理的,例如作为您经常运行的查询的优化。

请注意非规范化的缺点:数据完整性失败的风险,其他查询的性能不佳,限制了轻松更新数据的能力等等。

答案 1 :(得分:1)

如果不了解您的应用程序,就不可能说这是否是正确的方法 - 而是收集并考虑这些信息超出了问题的范围。

  

基本上,我获得了在特定日期为特定仓库提供服务的供应商的ID。

虽然目前还不清楚为什么你真的需要2个表,但是如果对数据进行非规范化会使得结果查询更快,那么需要注意的一点是你的数据在捕获之后不太可能改变,因此保持当前的结构具有物化视图将具有最小的开销。首先需要通过将子查询结果放入正确索引的表来测试查询性能。如果您获得了显着的性能优势,那么您需要考虑如何维护新表 - 您可以用新表替换现有表中的一个表,还是保留原始表并将数据填充到表中按批次或按触发器新表。

尝试一下并看看它有什么作用并不难 - 而且你会得到比这里任何人都能给你的更好的答案。

相关问题