diff --git a/django/db/backends/creation.py b/django/db/backends/creation.py
--- a/django/db/backends/creation.py
+++ b/django/db/backends/creation.py
@@ -133,21 +133,39 @@
                     (qn(r_table), qn(truncate_name(r_name, self.connection.ops.max_name_length())),
                     qn(r_col), qn(table), qn(col),
                     self.connection.ops.deferrable_sql()))
             del pending_references[model]
         return final_output
 
     def sql_indexes_for_model(self, model, style):
         "Returns the CREATE INDEX SQL statements for a single model"
+        from django.db.backends.util import truncate_name
+
         if not model._meta.managed or model._meta.proxy:
             return []
+
+        opts = model._meta
+        qn = self.connection.ops.quote_name
         output = []
+
         for f in model._meta.local_fields:
             output.extend(self.sql_indexes_for_field(model, f, style))
+
+        for field_constraints in opts.index_together:
+            i_name = '%s_%s' % (opts.db_table, self._digest(field_constraints))
+
+            output.append(
+                style.SQL_KEYWORD('CREATE INDEX') + ' ' +
+                style.SQL_TABLE(qn(truncate_name(i_name, self.connection.ops.max_name_length()))) + ' ' +
+                style.SQL_KEYWORD('ON') + ' ' +
+                style.SQL_TABLE(qn(opts.db_table)) + ' ' +
+                "(%s);" % ", ".join([style.SQL_FIELD(qn(opts.get_field(f).column)) for f in field_constraints])
+            )
+
         return output
 
     def sql_indexes_for_field(self, model, f, style):
         "Return the CREATE INDEX SQL statements for a single model field"
         from django.db.backends.util import truncate_name
 
         if f.db_index and not f.unique:
             qn = self.connection.ops.quote_name
diff --git a/django/db/models/options.py b/django/db/models/options.py
--- a/django/db/models/options.py
+++ b/django/db/models/options.py
@@ -12,27 +12,28 @@
 from django.utils.datastructures import SortedDict
 
 # Calculate the verbose_name by converting from InitialCaps to "lowercase with spaces".
 get_verbose_name = lambda class_name: re.sub('(((?<=[a-z])[A-Z])|([A-Z](?![A-Z]|$)))', ' \\1', class_name).lower().strip()
 
 DEFAULT_NAMES = ('verbose_name', 'verbose_name_plural', 'db_table', 'ordering',
                  'unique_together', 'permissions', 'get_latest_by',
                  'order_with_respect_to', 'app_label', 'db_tablespace',
-                 'abstract', 'managed', 'proxy', 'auto_created')
+                 'abstract', 'managed', 'proxy', 'auto_created', 'index_together')
 
 class Options(object):
     def __init__(self, meta, app_label=None):
         self.local_fields, self.local_many_to_many = [], []
         self.virtual_fields = []
         self.module_name, self.verbose_name = None, None
         self.verbose_name_plural = None
         self.db_table = ''
         self.ordering = []
         self.unique_together =  []
+        self.index_together =  []
         self.permissions =  []
         self.object_name, self.app_label = None, app_label
         self.get_latest_by = None
         self.order_with_respect_to = None
         self.db_tablespace = settings.DEFAULT_TABLESPACE
         self.admin = None
         self.meta = meta
         self.pk = None
@@ -75,24 +76,29 @@
                 if name.startswith('_'):
                     del meta_attrs[name]
             for attr_name in DEFAULT_NAMES:
                 if attr_name in meta_attrs:
                     setattr(self, attr_name, meta_attrs.pop(attr_name))
                 elif hasattr(self.meta, attr_name):
                     setattr(self, attr_name, getattr(self.meta, attr_name))
 
-            # unique_together can be either a tuple of tuples, or a single
+            # unique_together and index_together can be either a tuple of tuples, or a single
             # tuple of two strings. Normalize it to a tuple of tuples, so that
             # calling code can uniformly expect that.
             ut = meta_attrs.pop('unique_together', self.unique_together)
             if ut and not isinstance(ut[0], (tuple, list)):
                 ut = (ut,)
             self.unique_together = ut
 
+            it = meta_attrs.pop('index_together', self.index_together)
+            if it and not isinstance(it[0], (tuple, list)):
+                it = (it,)
+            self.index_together = it
+
             # verbose_name_plural is a special case because it uses a 's'
             # by default.
             if self.verbose_name_plural is None:
                 self.verbose_name_plural = string_concat(self.verbose_name, 's')
 
             # Any leftover attributes must be invalid.
             if meta_attrs != {}:
                 raise TypeError("'class Meta' got invalid attribute(s): %s" % ','.join(meta_attrs.keys()))
diff --git a/docs/ref/models/options.txt b/docs/ref/models/options.txt
--- a/docs/ref/models/options.txt
+++ b/docs/ref/models/options.txt
@@ -242,16 +242,35 @@
     appropriate ``UNIQUE`` statements are included in the ``CREATE TABLE``
     statement).
 
     For convenience, unique_together can be a single list when dealing with a single
     set of fields::
 
         unique_together = ("driver", "restaurant")
 
+``index_together``
+-------------------
+
+.. versionadded:: 1.4
+
+.. attribute:: Options.index_together
+
+    Sets of field names that, taken together, will be indexed::
+
+        index_together = (("driver", "restaurant"),)
+
+    This is a list of lists of fields that will indexed together. (i.e., the
+    appropriate ``CREATE INDEX`` statements will be created for this table.
+
+    For convenience, index_together can be a single list when dealing with a single
+    set of fields::
+
+        index_together = ("driver", "restaurant")
+
 ``verbose_name``
 ----------------
 
 .. attribute:: Options.verbose_name
 
     A human-readable name for the object, singular::
 
         verbose_name = "pizza"
diff --git a/tests/modeltests/basic/models.py b/tests/modeltests/basic/models.py
--- a/tests/modeltests/basic/models.py
+++ b/tests/modeltests/basic/models.py
@@ -8,11 +8,12 @@
 
 
 class Article(models.Model):
     headline = models.CharField(max_length=100, default='Default headline')
     pub_date = models.DateTimeField()
 
     class Meta:
         ordering = ('pub_date','headline')
+        index_together = ('headline', 'pub_date')
 
     def __unicode__(self):
         return self.headline
diff --git a/tests/modeltests/get_or_create/models.py b/tests/modeltests/get_or_create/models.py
--- a/tests/modeltests/get_or_create/models.py
+++ b/tests/modeltests/get_or_create/models.py
@@ -9,14 +9,17 @@
 from django.db import models
 
 
 class Person(models.Model):
     first_name = models.CharField(max_length=100)
     last_name = models.CharField(max_length=100)
     birthday = models.DateField()
 
+    class Meta:
+        index_together = (('first_name', 'last_name'), ('first_name', 'birthday'))
+
     def __unicode__(self):
         return u'%s %s' % (self.first_name, self.last_name)
 
 class ManualPrimaryKeyTest(models.Model):
     id = models.IntegerField(primary_key=True)
     data = models.CharField(max_length=100)
