Django如何使用TinyIntegerField或SmallIntegerField作为主键?

时间:2015-11-16 20:20:41

标签: django postgresql django-models

我想为少于255个选项创建一个应该呈现给用户的表,并使用1个字节的整数作为主键。类似于以下代码中的内容,但最好使用TinyIntegerField,如果可以创建一个。

class Category(models.Model):
    id = models.SmallIntegerField(auto_increment=True, primary_key=True)
    category = models.CharField(max_length=254, unique=True)

class Test(models.Model):
    category = models.ForeignKey(Category)
  1. 我假设Django中没有TinyInteger,因为那里 在Postgres不是一个人。为什么Postgres中没有tinyint?

  2. 在Django文档中,唯一的自动增量是AutoField,如何将自动增量应用于SmallIntegerField

2 个答案:

答案 0 :(得分:1)

您说要使用1个字节的整数作为主键。我说,不要打扰。

一个整数是4个字节,如果少于255个选项,则保存少于765(255 * 3)个字节。

为了比较,这行代码(包括空格):

    id = models.SmallIntegerField(auto_increment=True, primary_key=True)
ASCII中的

长度为72个字节(如果计算行结尾则为74个)。因此,如果您的选项少于72个,那么您的代码中浪费的字节数将超过您保存在数据库中的字节数。

你的想法是在最坏的情况下过早优化,并且只会引入一个可能的错误区域。

既然你坚持要答案......

基于this snippet for a BigAutoFieldinternals for a SmallIntegerField,此代码应该有效:

class TinyAutoField(fields.AutoField):

    def db_type(self):
        return "smallint AUTO_INCREMENT"

    def get_internal_type(self):
        return "SmallIntegerField"

    def to_python(self, value):
        if value is None:
            return value
        try:
            return int(value)
        except (TypeError, ValueError):
            raise exceptions.ValidationError(
                _("This value must be a short integer."))

我不会做数学计算,只是说这段代码的存储远远大于你在数据库中保存的字节数。更不用说调试自定义AutoField所需的时间。

答案 1 :(得分:1)

在django 3.0中,有2个字节的SmallAutoField

类似于AutoField,但仅允许值低于特定(与数据库有关)的限制。在Django支持的所有数据库中,从1到32767的值都是安全的。

id = models.SmallAutoField(primary_key=True)

Postgresql's smallest number type is 2 bytes (small int)。 尽管不小于1个字节,但至少将使用量减半。有人说这样做是不值得的,他们对FK表上的节省没有怎么想,在那里引用可能重复数百万/数十亿次,这等于节省了很多。