Warning: file_get_contents(/data/phpspider/zhask/data//catemap/2/django/24.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
Django 地址数据库模式-更多外键还是纯文本?_Django_Database_Database Schema - Fatal编程技术网

Django 地址数据库模式-更多外键还是纯文本?

Django 地址数据库模式-更多外键还是纯文本?,django,database,database-schema,Django,Database,Database Schema,我在为我的应用程序设计数据库时左右为难。基本上,我想要存储地址。我使用的是Django,但更多的是数据库设计问题 比如说,我有州、市和ZipCode的模型: class State(models.Model): short_name = models.CharField(_('state short name'), max_length=2, primary_key=True) name = models.CharField(_('state full name'), max_l

我在为我的应用程序设计数据库时左右为难。基本上,我想要存储地址。我使用的是Django,但更多的是数据库设计问题

比如说,我有州、市和ZipCode的模型:

class State(models.Model):
    short_name = models.CharField(_('state short name'), max_length=2, primary_key=True)
    name = models.CharField(_('state full name'), max_length=50)

class City(models.Model):
    name = models.CharField(_('city name'), max_length=100)
    state = models.ForeignKey(State)

class ZipCode(models.Model):
    code = models.CharField(_('zip code'), max_length=6)
    city = models.ForeignKey(City)
然后,我想存储一个地址。这是我的两难选择:我应该使用外键(或者只使用一个外键)还是将整个地址存储为CharFields?也就是说,我应该使用地址模型的第1、第2或第3个版本:

第1版:

class Address(models.Model):
    street = models.CharField(_('street address'), max_length=300)
    city = models.ForeignKey(City)
    zip_code = models.ForeignKey(ZipCode)
    state = models.ForeignKey(State)
    counter = models.IntegerField()
第二版:

class Address(models.Model):
    street = models.CharField(_('street address'), max_length=300)
    city = models.CharField(_('city'), max_length=300)
    zip_code = models.CharField(_('zip code'), max_length=6)
    state = models.CharField(_('state'), max_length=50)
    counter = models.IntegerField()
class Address(models.Model):
    street = models.CharField(_('street address'), max_length=300)
    zip_code = models.ForeignKey(ZipCode)
    counter = models.IntegerField()
第三版:

class Address(models.Model):
    street = models.CharField(_('street address'), max_length=300)
    city = models.CharField(_('city'), max_length=300)
    zip_code = models.CharField(_('zip code'), max_length=6)
    state = models.CharField(_('state'), max_length=50)
    counter = models.IntegerField()
class Address(models.Model):
    street = models.CharField(_('street address'), max_length=300)
    zip_code = models.ForeignKey(ZipCode)
    counter = models.IntegerField()
我的具体用例是,每个用户搜索要么生成计数器为0的新地址(如果不存在),要么更新现有地址(例如,递增计数器字段;这只是一个示例)。假设每秒搜索1次,约30%的冗余搜索

我对不同版本的注释:

第一:

  • 创建新记录的开销(最坏情况:需要创建新的城市&Zip;州已填充)
  • 更多连接的数据(不确定这是赞成还是反对?)
第二:

  • 快速创建新地址记录
  • 较少的“连接”数据(不确定这是赞成还是反对?)
第三:

  • 邮政编码已分配给城市,城市已分配给州,无需复制此数据
我只是不确定哪个模式更好,为什么。现在我使用的是“普通”数据,地址上没有外键,只有字符域,工作正常。但是我的网站正在成长,我想有一个坚实的基础。另外,我真的很好奇如何处理这样的问题


感谢您花时间阅读此文。

从概念上思考,这是否成立

  • 一个州有一个或多个城市
  • 一个城市有一个或多个邮政编码
  • 邮政编码有一个或多个街道地址
这里有一个相当清晰的层次结构。如果将其反映在数据库中,则会出现以下情况:

  • 持有ZipCode外键的地址
  • ZipCode持有城市的外键
  • 持有国家外键的城市
因此,您的州、市和ZipCode设计看起来不错;您应该通过选择选项3来完成它

以下是此设计的一些好处:

  • 您将避免更新异常。你永远不会遇到这样的情况:一个地址与来自加利福尼亚州的邮政编码相关,同时又与怀俄明州相关
  • 您将不会一次又一次地保留字符串“Illinois”-除了节省空间之外,如果您在三年后意识到您意外地键入了“Ilinois”,您将不需要在live数据库的地址表上执行大量更新脚本来纠正此问题
  • 如果一个州的边界发生了变化,一个曾经是亚利桑那州一部分的城市变成了新墨西哥州的一部分(好吧,这不太可能,但是为了坚持你的例子,请耐心听我说!),你只需要在city表中的一条记录上更新外键
  • 如果对相同的数据有不同的需求(报告?商业智能/分析?新的网站功能?),有这样一个坚实的结构,每个数据项只保存在一个地方,没有伪造的外键,这将清楚地表明要使用哪些数据,将有助于避免耗时和潜在问题的数据清理,并将减少开发时间。源系统中重复且不一致的数据占用了我作为商业智能/数据仓库开发人员的大量时间

展望未来,思考当前的数据库设计是否能够经得起网站的发展,您的想法是正确的。你越早解决这样的问题,它们就越容易改变,你可能遭受的干扰也就越少


如果您当前使用的是类似于选项2的东西,那么我猜您很可能在数据库的其他地方使用了类似的模式。如果是这种情况,并且您希望避免我上面提到的问题(以及其他问题),那么在数据库设计方面,特别是如何执行规范化方面,确实值得进行一些阅读或培训。

我感谢您全面的回答和解释,谢谢。我了解数据库设计和规范化的基础知识,我知道一致性数据库比不一致性数据库好。在这种特殊情况下,我主要关心的是性能/速度,因为地址搜索是最频繁的操作,我需要尽快返回结果(地址“upsert”只是过程的一部分)。您关于报告/BI的观点对我最有帮助,并说服我使用第三版。谢谢大家!@iyn很高兴它有所帮助,也很高兴在数据质量的斗争中赢得了一些人的支持!;)在保持数据完整性的同时进行优化时,最安全的计划是首先建立一个规范化的结构。然后确保有合适的索引,并在必要/可能的地方调整查询。有时,非规范化(或使用非关系数据库)是正确的答案,但与所有优化一样,避免过早地进行。