views:

486

answers:

5

I'm wonder why it's provided. The field is database dependent, doesn't that make it totally unreliable to use?

I want to store birth year in a model, kinda like

class Person(models.Model):
  name = models.CharField(max_length=256)
  born = models.IntegerField()

Of course this requires very little space, it should always be 4 "characters" long, so a PositiveSmallIntegerField would maybe fit, but why should I choose it instead of normal IntegerField?

A: 

You would choose SmallIntegerField if you wanted to save space in the database. The limit on the value is database-dependent, but that doesn't make it unreliable. It just means you have to know what database system you are using, and find out what the limit is for that system.

Ned Batchelder
Well, wouldn't to make it unreliable in the sense that you can't count on switching the backend DB to not break things?
Davy8
I don't count that as unreliable. That's portability. As engineers, we have to analyze problems and tools, then combine the tools in a way that solves the problems. If your problem allows you to only use databases that support SmallIntegerField, and space in the database is a potential issue, then SmallIntegerField is a great solution with no unreliability.
Ned Batchelder
+1  A: 

This is one of those things that is the way it is because it got that way.

Django supports SmallIntegerField because Django grew up on PostgreSQL, and PostgreSQL supports smallint. The PosgreSQL docs say

The smallint type is generally only used if disk space is at a premium.

While it seems kind of quaint now, when 1TB disks can be had at the corner store, it wasn't all that long ago when disks were a lot smaller, costing significantly more per byte. Memory, too. Using a smallint (where appropriate) in an index means fitting more row indexes into RAM cache, which meant better performance.

Dave W. Smith
+6  A: 

Performance on many RDBMs can be heavily dependent on row size. While a "purist" approach might say that the application should be completely independent of the underlying data structure, over many rows improvements like using a smaller integer could shave gigabytes off table size, which makes more of the table fit in memory, which drastically improves performance. It's the Brief part of the ABCs.

I would use a small integer like this for say, a primary key on a table that would always have <100 rows, especially when this is stored as a foreign key in a table I expect to grow very large. While the size is implementation defined, it's safe to assume that it is greater than 127 at the very least.

Todd Gardner
SmallIntegerField is also handy when you have a fixed number of options, and are using the choices parameter. For example: born = models.SmallIntegerField(choices=((1, '1960-1969'), 2, '1970 - 1970))
Chip Tol
+2  A: 

It's not totally unreliable. SMALLINT is part of the SQL standard and certainly MySQL and PostgreSQL both have small integer types that go from -32768 to +32767

Anentropic
A: 

Year is date without taking care of months and days. Choose the DateField and hence enjoy all the power Django provides to you. Since you store born yeas, this also allows you in the future to simply accept months and days.

Török Gábor
Because I don't want a date, I want a year. And that is not a good fit with a DateField.
Velmont
@Velmont: I think year *is* date.
Török Gábor
No, a date has month and day as well.
Velmont
I don't do that because it is hard to use date objects as years. It is also *wrong*. Because I would effectively have to put a date and month in there (because it is not possible without), HENCE that makes it 100% wrong. In the beginning I started with DateTime, but found out that it was not a smart move in the end.
Velmont