diff --git a/core/includes/database.inc b/core/includes/database.inc
index 75744f4..240f6ee 100644
--- a/core/includes/database.inc
+++ b/core/includes/database.inc
@@ -905,16 +905,22 @@ function db_drop_unique_key($table, $name) {
  *   The name of the index.
  * @param array $fields
  *   An array of field names.
+ * @param array $spec
+ *   The table specification of the table to be altered, as taken from a schema
+ *   definition. See \Drupal\Core\Database\Schema::addIndex() for how to obtain
+ *   this specification.
  *
  * @deprecated as of Drupal 8.0.x, will be removed in Drupal 9.0.0. Instead, get
  *   a database connection injected into your service from the container, get
  *   its schema driver, and call addIndex() on it. E.g.
- *   $injected_database->schema()->addIndex($table, $name, $fields);
+ *   $injected_database->schema()->addIndex($table, $name, $fields, $spec);
  *
+ * @see hook_schema()
+ * @see schemaapi
  * @see \Drupal\Core\Database\Schema::addIndex()
  */
-function db_add_index($table, $name, $fields) {
-  return Database::getConnection()->schema()->addIndex($table, $name, $fields);
+function db_add_index($table, $name, $fields, array $spec) {
+  return Database::getConnection()->schema()->addIndex($table, $name, $fields, $spec);
 }
 
 /**
diff --git a/core/lib/Drupal/Core/Database/Driver/mysql/Schema.php b/core/lib/Drupal/Core/Database/Driver/mysql/Schema.php
index 8f5b710..69799fa 100644
--- a/core/lib/Drupal/Core/Database/Driver/mysql/Schema.php
+++ b/core/lib/Drupal/Core/Database/Driver/mysql/Schema.php
@@ -299,14 +299,14 @@ protected function createKeysSql($spec) {
    * Shortens indexes to 191 characters if they apply to utf8mb4-encoded
    * fields, in order to comply with the InnoDB index limitation of 756 bytes.
    *
-   * @param $spec
+   * @param array $spec
    *   The table specification.
    *
    * @return array
    *   List of shortened indexes.
    */
-  protected function getNormalizedIndexes($spec) {
-    $indexes = $spec['indexes'];
+  protected function getNormalizedIndexes(array $spec) {
+    $indexes = isset($spec['indexes']) ? $spec['indexes'] : [];
     foreach ($indexes as $index_name => $index_fields) {
       foreach ($index_fields as $index_key => $index_field) {
         // Get the name of the field from the index specification.
@@ -486,7 +486,10 @@ public function dropUniqueKey($table, $name) {
     return TRUE;
   }
 
-  public function addIndex($table, $name, $fields) {
+  /**
+   * {@inheritdoc}
+   */
+  public function addIndex($table, $name, $fields, array $spec) {
     if (!$this->tableExists($table)) {
       throw new SchemaObjectDoesNotExistException(t("Cannot add index @name to table @table: table doesn't exist.", array('@table' => $table, '@name' => $name)));
     }
@@ -494,7 +497,10 @@ public function addIndex($table, $name, $fields) {
       throw new SchemaObjectExistsException(t("Cannot add index @name to table @table: index already exists.", array('@table' => $table, '@name' => $name)));
     }
 
-    $this->connection->query('ALTER TABLE {' . $table . '} ADD INDEX `' . $name . '` (' . $this->createKeySql($fields) . ')');
+    $spec['indexes'][$name] = $fields;
+    $indexes = $this->getNormalizedIndexes($spec);
+
+    $this->connection->query('ALTER TABLE {' . $table . '} ADD INDEX `' . $name . '` (' . $this->createKeySql($indexes[$name]) . ')');
   }
 
   public function dropIndex($table, $name) {
diff --git a/core/lib/Drupal/Core/Database/Driver/pgsql/Schema.php b/core/lib/Drupal/Core/Database/Driver/pgsql/Schema.php
index e3062dd..6025a70 100644
--- a/core/lib/Drupal/Core/Database/Driver/pgsql/Schema.php
+++ b/core/lib/Drupal/Core/Database/Driver/pgsql/Schema.php
@@ -637,7 +637,10 @@ public function dropUniqueKey($table, $name) {
     return TRUE;
   }
 
-  public function addIndex($table, $name, $fields) {
+  /**
+   * {@inheritdoc}
+   */
+  public function addIndex($table, $name, $fields, array $spec) {
     if (!$this->tableExists($table)) {
       throw new SchemaObjectDoesNotExistException(t("Cannot add index @name to table @table: table doesn't exist.", array('@table' => $table, '@name' => $name)));
     }
@@ -779,7 +782,10 @@ protected function _createKeys($table, $new_keys) {
     }
     if (isset($new_keys['indexes'])) {
       foreach ($new_keys['indexes'] as $name => $fields) {
-        $this->addIndex($table, $name, $fields);
+        // Even though $new_keys is not a full schema it still has 'indexes' and
+        // so is a partial schema. Technically addIndex() doesn't do anything
+        // with it so passing an empty array would work as well.
+        $this->addIndex($table, $name, $fields, $new_keys);
       }
     }
   }
diff --git a/core/lib/Drupal/Core/Database/Driver/sqlite/Schema.php b/core/lib/Drupal/Core/Database/Driver/sqlite/Schema.php
index 3ac3811..f417b18 100644
--- a/core/lib/Drupal/Core/Database/Driver/sqlite/Schema.php
+++ b/core/lib/Drupal/Core/Database/Driver/sqlite/Schema.php
@@ -582,7 +582,10 @@ protected function mapKeyDefinition(array $key_definition, array $mapping) {
     return $key_definition;
   }
 
-  public function addIndex($table, $name, $fields) {
+  /**
+   * {@inheritdoc}
+   */
+  public function addIndex($table, $name, $fields, array $spec) {
     if (!$this->tableExists($table)) {
       throw new SchemaObjectDoesNotExistException(t("Cannot add index @name to table @table: table doesn't exist.", array('@table' => $table, '@name' => $name)));
     }
diff --git a/core/lib/Drupal/Core/Database/Schema.php b/core/lib/Drupal/Core/Database/Schema.php
index 4ebfd40..b9ff670 100644
--- a/core/lib/Drupal/Core/Database/Schema.php
+++ b/core/lib/Drupal/Core/Database/Schema.php
@@ -413,13 +413,51 @@ public function fieldExists($table, $column) {
    *   @code
    *     $fields = ['foo', ['bar', 4]];
    *   @endcode
+   * @param array $spec
+   *   The table specification for the table to be altered. This is used in
+   *   order to be able to ensure that the index length is not too long.
+   *   This schema definition can usually be obtained through hook_schema(), or
+   *   in case the table was created by the Entity API, through the schema
+   *   handler listed in the entity class definition. For reference, see
+   *   SqlContentEntityStorageSchema::getDedicatedTableSchema() and
+   *   SqlContentEntityStorageSchema::getSharedTableFieldSchema().
+   *
+   *   In order to prevent human error, it is recommended to pass in the
+   *   complete table specification. However, in the edge case of the complete
+   *   table specification not being available, we can pass in a partial table
+   *   definition containing only the fields that apply to the index:
+   *   @code
+   *   $spec = [
+   *     // Example partial specification for a table:
+   *     'fields' => [
+   *       'example_field' => [
+   *         'description' => 'An example field',
+   *         'type' => 'varchar',
+   *         'length' => 32,
+   *         'not null' => TRUE,
+   *         'default' => '',
+   *       ],
+   *     ],
+   *     'indexes' => [
+   *       'table_example_field' => ['example_field'],
+   *     ],
+   *   ];
+   *   @endcode
+   *   Note that the above is a partial table definition and that we would
+   *   usually pass a complete table definition as obtained through
+   *   hook_schema() instead.
+   *
+   * @see schemaapi
+   * @see hook_schema()
    *
    * @throws \Drupal\Core\Database\SchemaObjectDoesNotExistException
    *   If the specified table doesn't exist.
    * @throws \Drupal\Core\Database\SchemaObjectExistsException
    *   If the specified table already has an index by that name.
+   *
+   * @todo remove the $spec argument whenever schema introspection is added.
    */
-  abstract public function addIndex($table, $name, $fields);
+  abstract public function addIndex($table, $name, $fields, array $spec);
 
   /**
    * Drop an index.
diff --git a/core/lib/Drupal/Core/Entity/Sql/SqlContentEntityStorageSchema.php b/core/lib/Drupal/Core/Entity/Sql/SqlContentEntityStorageSchema.php
index 8a96e51..3ac81ab 100644
--- a/core/lib/Drupal/Core/Entity/Sql/SqlContentEntityStorageSchema.php
+++ b/core/lib/Drupal/Core/Entity/Sql/SqlContentEntityStorageSchema.php
@@ -330,9 +330,13 @@ public function onEntityTypeUpdate(EntityTypeInterface $entity_type, EntityTypeI
       // Create new indexes and unique keys.
       $entity_schema = $this->getEntitySchema($entity_type, TRUE);
       foreach ($this->getEntitySchemaData($entity_type, $entity_schema) as $table_name => $schema) {
+        // Add fields schema because database driver may depend on this data to
+        // perform index normalization.
+        $schema['fields'] = $entity_schema[$table_name]['fields'];
+
         if (!empty($schema['indexes'])) {
           foreach ($schema['indexes'] as $name => $specifier) {
-            $schema_handler->addIndex($table_name, $name, $specifier);
+            $schema_handler->addIndex($table_name, $name, $specifier, $schema);
           }
         }
         if (!empty($schema['unique keys'])) {
@@ -1139,7 +1143,7 @@ protected function createSharedTableSchema(FieldStorageDefinitionInterface $stor
                 // Check if the index exists because it might already have been
                 // created as part of the earlier entity type update event.
                 if (!$schema_handler->indexExists($table_name, $name)) {
-                  $schema_handler->addIndex($table_name, $name, $specifier);
+                  $schema_handler->addIndex($table_name, $name, $specifier, $schema[$table_name]);
                 }
               }
             }
@@ -1302,8 +1306,8 @@ protected function updateDedicatedTableSchema(FieldStorageDefinitionInterface $s
               $real_columns[] = $table_mapping->getFieldColumnName($storage_definition, $column_name);
             }
           }
-          $this->database->schema()->addIndex($table, $real_name, $real_columns);
-          $this->database->schema()->addIndex($revision_table, $real_name, $real_columns);
+          $this->database->schema()->addIndex($table, $real_name, $real_columns, $schema);
+          $this->database->schema()->addIndex($revision_table, $real_name, $real_columns, $schema);
         }
       }
       $this->saveFieldSchemaData($storage_definition, $this->getDedicatedTableSchema($storage_definition));
@@ -1380,7 +1384,7 @@ protected function updateSharedTableSchema(FieldStorageDefinitionInterface $stor
             // Create new indexes and unique keys.
             if (!empty($schema[$table_name]['indexes'])) {
               foreach ($schema[$table_name]['indexes'] as $name => $specifier) {
-                $schema_handler->addIndex($table_name, $name, $specifier);
+                $schema_handler->addIndex($table_name, $name, $specifier, $schema[$table_name]);
               }
             }
             if (!empty($schema[$table_name]['unique keys'])) {
diff --git a/core/modules/system/src/Tests/Database/SchemaTest.php b/core/modules/system/src/Tests/Database/SchemaTest.php
index 1e77084..e2260d5 100644
--- a/core/modules/system/src/Tests/Database/SchemaTest.php
+++ b/core/modules/system/src/Tests/Database/SchemaTest.php
@@ -99,7 +99,7 @@ function testSchema() {
     $index_exists = Database::getConnection()->schema()->indexExists('test_table', 'test_field');
     $this->assertIdentical($index_exists, FALSE, 'Fake index does not exists');
     // Add index.
-    db_add_index('test_table', 'test_field', array('test_field'));
+    db_add_index('test_table', 'test_field', array('test_field'), $table_specification);
     // Test for created index and test for the boolean result of indexExists().
     $index_exists = Database::getConnection()->schema()->indexExists('test_table', 'test_field');
     $this->assertIdentical($index_exists, TRUE, 'Index created.');
@@ -295,6 +295,30 @@ function testIndexLength() {
     );
     db_create_table('test_table_index_length', $table_specification);
 
+    // Add a separate index.
+    $schema_object = Database::getConnection()->schema();
+    $schema_object->addIndex('test_table_index_length', 'test_separate', [['test_field_text', 200]], $table_specification);
+    $table_specification_with_new_index = $table_specification;
+    $table_specification_with_new_index['indexes']['test_separate'] = [['test_field_text', 200]];
+
+    // Ensure that the exceptions of addIndex are thrown as expected.
+
+    try {
+      $schema_object->addIndex('test_table_index_length', 'test_separate', [['test_field_text', 200]], $table_specification);
+      $this->fail('\Drupal\Core\Database\SchemaObjectExistsException exception missed.');
+    }
+    catch (SchemaObjectExistsException $e) {
+      $this->pass('\Drupal\Core\Database\SchemaObjectExistsException thrown when index already exists.');
+    }
+
+    try {
+      $schema_object->addIndex('test_table_non_existing', 'test_separate', [['test_field_text', 200]], $table_specification);
+      $this->fail('\Drupal\Core\Database\SchemaObjectDoesNotExistException exception missed.');
+    }
+    catch (SchemaObjectDoesNotExistException $e) {
+      $this->pass('\Drupal\Core\Database\SchemaObjectDoesNotExistException thrown when index already exists.');
+    }
+
     // Get index information.
     $results = db_query('SHOW INDEX FROM {test_table_index_length}');
     $expected_lengths = array(
@@ -316,11 +340,14 @@ function testIndexLength() {
         'test_field_string_ascii_long' => 200,
         'test_field_string_short' => NULL,
       ),
+      'test_separate' => array(
+        'test_field_text' => 191,
+      ),
     );
 
     // Count the number of columns defined in the indexes.
     $column_count = 0;
-    foreach ($table_specification['indexes'] as $index) {
+    foreach ($table_specification_with_new_index['indexes'] as $index) {
       foreach ($index as $field) {
         $column_count++;
       }
diff --git a/core/modules/system/src/Tests/Entity/EntityDefinitionUpdateTest.php b/core/modules/system/src/Tests/Entity/EntityDefinitionUpdateTest.php
index 03cb236..8ae7fa5 100644
--- a/core/modules/system/src/Tests/Entity/EntityDefinitionUpdateTest.php
+++ b/core/modules/system/src/Tests/Entity/EntityDefinitionUpdateTest.php
@@ -7,6 +7,7 @@
 
 namespace Drupal\system\Tests\Entity;
 
+use Drupal\Core\Database\Database;
 use Drupal\Core\Database\DatabaseExceptionWrapper;
 use Drupal\Core\Database\IntegrityConstraintViolationException;
 use Drupal\Core\Entity\EntityDefinitionUpdateManagerInterface;
@@ -626,4 +627,48 @@ public function testSingleActionCalls() {
     $this->assertTrue($this->database->schema()->tableExists('entity_test_update_revision'), "The 'entity_test_update_revision' table has been created.");
   }
 
+  /**
+   * Ensures that a new field and index on a shared table are created.
+   *
+   * @see Drupal\Core\Entity\Sql\SqlContentEntityStorageSchema::createSharedTableSchema
+   */
+  public function testCreateFieldAndIndexOnSharedTable() {
+    $this->addBaseField();
+    $this->addBaseFieldIndex();
+    $this->entityDefinitionUpdateManager->applyUpdates();
+    $this->assertTrue($this->database->schema()->fieldExists('entity_test_update', 'new_base_field'), "New field 'new_base_field' has been created on the 'entity_test_update' table.");
+    $this->assertTrue($this->database->schema()->indexExists('entity_test_update', 'entity_test_update_field__new_base_field'), "New index 'entity_test_update_field__new_base_field' has been created on the 'entity_test_update' table.");
+    // Check index size in for MySQL.
+    if (Database::getConnection()->driver() == 'mysql') {
+      $result = Database::getConnection()->query('SHOW INDEX FROM {entity_test_update} WHERE key_name = \'entity_test_update_field__new_base_field\' and column_name = \'new_base_field\'')->fetchObject();
+      $this->assertEqual(191, $result->Sub_part, 'The index length has been restricted to 191 characters for UTF8MB4 compatibility.');
+    }
+  }
+
+  /**
+   * Ensures that a new entity level index is created when data exists.
+   *
+   * @see Drupal\Core\Entity\Sql\SqlContentEntityStorageSchema::onEntityTypeUpdate
+   */
+  public function testCreateIndexUsingEntityStorageSchemaWithData() {
+    // Save an entity.
+    $name = $this->randomString();
+    $storage = $this->entityManager->getStorage('entity_test_update');
+    $entity = $storage->create(array('name' => $name));
+    $entity->save();
+
+    // Create an index.
+    $indexes = array(
+      'entity_test_update__type_index' => array('type'),
+    );
+    $this->state->set('entity_test_update.additional_entity_indexes', $indexes);
+    $this->entityDefinitionUpdateManager->applyUpdates();
+    $this->assertTrue($this->database->schema()->indexExists('entity_test_update', 'entity_test_update__type_index'), "New index 'entity_test_update__type_index' has been created on the 'entity_test_update' table.");
+    // Check index size in for MySQL.
+    if (Database::getConnection()->driver() == 'mysql') {
+      $result = Database::getConnection()->query('SHOW INDEX FROM {entity_test_update} WHERE key_name = \'entity_test_update__type_index\' and column_name = \'type\'')->fetchObject();
+      $this->assertEqual(191, $result->Sub_part, 'The index length has been restricted to 191 characters for UTF8MB4 compatibility.');
+    }
+  }
+
 }
diff --git a/core/modules/system/tests/modules/update_test_schema/update_test_schema.install b/core/modules/system/tests/modules/update_test_schema/update_test_schema.install
index b6aa9c3..972f901 100644
--- a/core/modules/system/tests/modules/update_test_schema/update_test_schema.install
+++ b/core/modules/system/tests/modules/update_test_schema/update_test_schema.install
@@ -35,7 +35,14 @@ function update_test_schema_schema() {
    * Schema version 8001.
    */
   function update_test_schema_update_8001() {
+    $table = [
+      'fields' => [
+        'a' => ['type' => 'int', 'not null' => TRUE],
+        'b' => ['type' => 'blob', 'not null' => FALSE],
+      ],
+    ];
+
     // Add a column.
-    db_add_index('update_test_schema_table', 'test', ['a']);
+    db_add_index('update_test_schema_table', 'test', ['a'], $table);
   }
 }
