Upgrade to Pro — share decks privately, control downloads, hide ads and more …

Going Beyond Django ORM with Postgres

Going Beyond Django ORM with Postgres

Craig Kerstiens

March 17, 2013
Tweet

More Decks by Craig Kerstiens

Other Decks in Technology

Transcript

  1. Datatypes Conditional Indexes Transactional DDL Foreign Data Wrappers Concurrent Index

    Creation Extensions Common Table Expressions Fast Column Addition Listen/Notify Table Inheritance Per Transaction sync replication Window functions NoSQL inside SQL Momentum TLDR
  2. Limitations? Django attempts to support as many features as possible

    on all database backends. However, not all database backends are alike, and we’ve had to make design decisions on which features to support and which assumptions we can make safely.
  3. Datatypes smallint bigint integer numeric float serial money char varchar

    text bytea timestamp timestamptz date time timetz interval boolean enum point line polygon box circle path inet cidr macaddr tsvector tsquery array XML UUID
  4. Datatypes smallint bigint integer numeric float serial money char varchar

    text bytea timestamp timestamptz date time timetz interval boolean enum point line polygon box circle path cidr macaddr tsvector tsquery array XML UUID inet
  5. Datatypes smallint bigint integer numeric float serial money char varchar

    text bytea timestamp timestamptz date time timetz interval boolean enum point line polygon box circle path cidr macaddr tsvector tsquery array XML UUID inet
  6. Datatypes smallint bigint integer numeric float serial money char varchar

    text bytea timestamp timestamptz date time timetz interval boolean enum point line polygon box circle path cidr macaddr tsvector tsquery array XML UUID inet
  7. Datatypes smallint bigint integer numeric float serial money char varchar

    text bytea timestamp timestamptz date time timetz interval boolean enum point line polygon box circle path inet cidr macaddr tsvector tsquery array XML UUID
  8. Arrays CREATE TABLE item ( id serial NOT NULL, name

    varchar (255), tags varchar(255) [], created_at timestamp );
  9. Arrays CREATE TABLE item ( id serial NOT NULL, name

    varchar (255), tags varchar(255) [], created_at timestamp );
  10. Arrays INSERT INTO item VALUES (1, 'Django Pony', '{“Programming”,”Animal”}', now());

    INSERT INTO item VALUES (2, 'Ruby Gem', '{“Programming”,”Jewelry”}', now());
  11. Arrays INSERT INTO item VALUES (1, 'Django Pony', '{“Programming”,”Animal”}', now());

    INSERT INTO item VALUES (2, 'Ruby Gem', '{“Programming”,”Jewelry”}', now());
  12. Django pip install djorm-ext-pgarray pip install djorm-ext-expressions models.py: from djorm_pgarray.fields

    import ArrayField from djorm_expressions.models import ExpressionManager class Item(models.Model): name = models.CharField(max_length=255) tags = ArrayField(dbtype="varchar(255)") created_at = models.DateTimeField(auto_now=True)
  13. Django pip install djorm-ext-pgarray pip install djorm-ext-expressions models.py: from djorm_pgarray.fields

    import ArrayField from djorm_expressions.models import ExpressionManager class Item(models.Model): name = models.CharField(max_length=255) tags = ArrayField(dbtype="varchar(255)") created_at = models.DateTimeField(auto_now=True)
  14. Django i = Item( name='Django Pony', tags=['Programming','Animal']) i.save() qs =

    Item.objects.where( SqlExpression("tags", "@>", ['programming']) )
  15. Django i = Item( name='Django Pony', tags=['Programming','Animal']) i.save() qs =

    Item.objects.where( SqlExpression("tags", "@>", ['programming']) )
  16. dblink hstore citext ltree isn cube pgcrypto tablefunc uuid-ossp earthdistance

    trigram fuzzystrmatch pgrowlocks pgstattuple btree_gist dict_int dict_xsyn unaccent Extensions
  17. NoSQL in your SQL CREATE EXTENSION hstore; CREATE TABLE item

    ( id integer NOT NULL, name varchar(255), data hstore, );
  18. NoSQL in your SQL CREATE EXTENSION hstore; CREATE TABLE item

    ( id integer NOT NULL, name varchar(255), data hstore, );
  19. NoSQL in your SQL INSERT INTO items VALUES ( 1,

    'Pony', 'rating => "4.0", color => “Pink”', );
  20. NoSQL in your SQL INSERT INTO items VALUES ( 1,

    'Pony', 'rating => "4.0", color => “Pink”', );
  21. Django pip install django-hstore from django.db import models from django_hstore

    import hstore class Item(models.Model): name = models.CharField(max_length=250) data = hstore.DictionaryField(db_index=True) objects = hstore.Manager() def __unicode__(self): return self.name
  22. Django pip install django-hstore from django.db import models from django_hstore

    import hstore class Item(models.Model): name = models.CharField(max_length=250) data = hstore.DictionaryField(db_index=True) objects = hstore.Manager() def __unicode__(self): return self.name
  23. SELECT '{"id":1,"email": "[email protected]",}'::json; JSON V8 w/ PLV8 create or replace

    function js(src text) returns text as $$ return eval( "(function() { " + src + "})" )(); $$ LANGUAGE plv8;
  24. SELECT '{"id":1,"email": "[email protected]",}'::json; JSON V8 w/ PLV8 create or replace

    function js(src text) returns text as $$ return eval( "(function() { " + src + "})" )(); $$ LANGUAGE plv8; JS Injection in DB: Bad Idea
  25. Trunk pip install celery trunk psql < sql/*.sql celery worker

    -A tasks --loglevel=info ipython -i tasks.py >>> add.delay(2, 2)
  26. Trunk pip install celery trunk psql < sql/*.sql celery worker

    -A tasks --loglevel=info ipython -i tasks.py >>> add.delay(2, 2)
  27. Trunk from celery import Celery celery = Celery('tasks') celery.config_from_object({ 'BROKER_URL':

    'trunk.transport.Transport:// localhost/trunk', }) @celery.task def add(x, y): return x + y
  28. Trunk from celery import Celery celery = Celery('tasks') celery.config_from_object({ 'BROKER_URL':

    'trunk.transport.Transport:// localhost/trunk', }) @celery.task def add(x, y): return x + y
  29. Full Text Search CREATE TABLE posts ( id serial, title

    varchar(255), content text, tags varchar(255)[], post_text tsvector ); CREATE INDEX posttext_gin ON posts USING GIN(post_text); CREATE TRIGGER update_posttext BEFORE INSERT OR UPDATE ON posts FOR EACH ROW EXECUTE PROCEDURE tsvector_update_trigger( ‘PostText’,‘english’,title, content, tags);
  30. Full Text Search CREATE TABLE posts ( id serial, title

    varchar(255), content text, tags varchar(255)[], post_text tsvector ); CREATE INDEX posttext_gin ON posts USING GIN(post_text); CREATE TRIGGER update_posttext BEFORE INSERT OR UPDATE ON posts FOR EACH ROW EXECUTE PROCEDURE tsvector_update_trigger( ‘PostText’,‘english’,title, content, tags);
  31. Django from djorm_pgfulltext.models import SearchManager from djorm_pgfulltext.fields import VectorField from

    django.db import models class Posts(models.Model): title = models.CharField(max_length=200) content = models.TextField() search_index = VectorField() objects = SearchManager( fields = ('title', 'content'), config = 'pg_catalog.english', search_field = 'search_index', auto_update_search_field = True )
  32. Django from djorm_pgfulltext.models import SearchManager from djorm_pgfulltext.fields import VectorField from

    django.db import models class Posts(models.Model): title = models.CharField(max_length=200) content = models.TextField() search_index = VectorField() objects = SearchManager( fields = ('title', 'content'), config = 'pg_catalog.english', search_field = 'search_index', auto_update_search_field = True )
  33. Indexes B-Tree Generalized Inverted Index (GIN) Generalized Search Tree (GIST)

    K Nearest Neighbors (KNN) Space Partitioned GIST (SP-GIST)
  34. Indexes B-Tree Generalized Inverted Index (GIN) Generalized Search Tree (GIST)

    K Nearest Neighbors (KNN) Space Partitioned GIST (SP-GIST)
  35. Indexes B-Tree Generalized Inverted Index (GIN) Generalized Search Tree (GIST)

    K Nearest Neighbors (KNN) Space Partitioned GIST (SP-GIST)
  36. Django pip install django-db-tools settings.py MIDDLEWARE_CLASSES = ( # ...

    'dbtools.middleware.ReadOnlyMiddleware', # ... ) READ_ONLY_MODE = True
  37. Django pip install django-db-tools settings.py MIDDLEWARE_CLASSES = ( # ...

    'dbtools.middleware.ReadOnlyMiddleware', # ... ) READ_ONLY_MODE = True
  38. Django pip install django-db-tools settings.py MIDDLEWARE_CLASSES = ( # ...

    'dbtools.middleware.ReadOnlyMiddleware', # ... ) READ_ONLY_MODE = os.environ[‘READ_ONLY_MODE']
  39. Django pip install django-db-tools settings.py MIDDLEWARE_CLASSES = ( # ...

    'dbtools.middleware.ReadOnlyMiddleware', # ... ) READ_ONLY_MODE = os.environ[‘READ_ONLY_MODE']
  40. django-postgrespool import dj_database_url import django_postgrespool DATABASE = { 'default': dj_database_url.config()

    } DATABASES['default']['ENGINE'] = 'django_postgrespool' SOUTH_DATABASE_ADAPTERS = { 'default': 'south.db.postgresql_psycopg2' }
  41. django-postgrespool import dj_database_url import django_postgrespool DATABASE = { 'default': dj_database_url.config()

    } DATABASES['default']['ENGINE'] = 'django_postgrespool' SOUTH_DATABASE_ADAPTERS = { 'default': 'south.db.postgresql_psycopg2' }
  42. Limitations? Django attempts to support as many features as possible

    on all database backends. However, not all database backends are alike, and we’ve had to make design decisions on which features to support and which assumptions we can make safely.