diff --git a/core/lib/Drupal/Core/Database/Driver/mysql/Schema.php b/core/lib/Drupal/Core/Database/Driver/mysql/Schema.php
index 28552fa..52d01b7 100644
--- a/core/lib/Drupal/Core/Database/Driver/mysql/Schema.php
+++ b/core/lib/Drupal/Core/Database/Driver/mysql/Schema.php
@@ -377,6 +377,7 @@ public function renameTable($table, $new_name) {
       throw new SchemaObjectExistsException(t("Cannot rename @table to @table_new: table @table_new already exists.", array('@table' => $table, '@table_new' => $new_name)));
     }
 
+    parent::renameTable($table, $new_name);
     $info = $this->getPrefixInfo($new_name);
     return $this->connection->query('ALTER TABLE {' . $table . '} RENAME TO `' . $info['table'] . '`');
   }
@@ -387,7 +388,7 @@ public function dropTable($table) {
     }
 
     $this->connection->query('DROP TABLE {' . $table . '}');
-    return TRUE;
+    return parent::dropTable($table);
   }
 
   public function addField($table, $field, $spec, $keys_new = array()) {
@@ -398,6 +399,8 @@ public function addField($table, $field, $spec, $keys_new = array()) {
       throw new SchemaObjectExistsException(t("Cannot add field @table.@field: field already exists.", array('@field' => $field, '@table' => $table)));
     }
 
+    parent::addField($table, $field, $spec, $keys_new);
+
     $fixnull = FALSE;
     if (!empty($spec['not null']) && !isset($spec['default'])) {
       $fixnull = TRUE;
@@ -426,7 +429,7 @@ public function dropField($table, $field) {
     }
 
     $this->connection->query('ALTER TABLE {' . $table . '} DROP `' . $field . '`');
-    return TRUE;
+    return parent::dropField($table, $field);
   }
 
   public function fieldSetDefault($table, $field, $default) {
@@ -526,6 +529,8 @@ public function changeField($table, $field, $field_new, $spec, $keys_new = array
       throw new SchemaObjectExistsException(t("Cannot rename field @table.@name to @name_new: target field already exists.", array('@table' => $table, '@name' => $field, '@name_new' => $field_new)));
     }
 
+    parent::changeField($table, $field, $field_new, $spec, $keys_new);
+
     $sql = 'ALTER TABLE {' . $table . '} CHANGE `' . $field . '` ' . $this->createFieldSql($field_new, $this->processField($spec));
     if ($keys_sql = $this->createKeysSql($keys_new)) {
       $sql .= ', ADD ' . implode(', ADD ', $keys_sql);
diff --git a/core/lib/Drupal/Core/Database/Driver/pgsql/Schema.php b/core/lib/Drupal/Core/Database/Driver/pgsql/Schema.php
index 06b7540..dc57866 100644
--- a/core/lib/Drupal/Core/Database/Driver/pgsql/Schema.php
+++ b/core/lib/Drupal/Core/Database/Driver/pgsql/Schema.php
@@ -458,6 +458,8 @@ function renameTable($table, $new_name) {
       throw new SchemaObjectExistsException(t("Cannot rename @table to @table_new: table @table_new already exists.", array('@table' => $table, '@table_new' => $new_name)));
     }
 
+    parent::renameTable($table, $new_name);
+
     // Get the schema and tablename for the old table.
     $old_full_name = $this->connection->prefixTables('{' . $table . '}');
     list($old_schema, $old_table_name) = strpos($old_full_name, '.') ? explode('.', $old_full_name) : array('public', $old_full_name);
@@ -511,7 +513,7 @@ public function dropTable($table) {
 
     $this->connection->query('DROP TABLE {' . $table . '}');
     $this->resetTableInformation($table);
-    return TRUE;
+    return parent::dropTable($table);
   }
 
   public function addField($table, $field, $spec, $new_keys = array()) {
@@ -522,6 +524,8 @@ public function addField($table, $field, $spec, $new_keys = array()) {
       throw new SchemaObjectExistsException(t("Cannot add field @table.@field: field already exists.", array('@field' => $field, '@table' => $table)));
     }
 
+    parent::addField($table, $field, $spec, $new_keys);
+
     $fixnull = FALSE;
     if (!empty($spec['not null']) && !isset($spec['default'])) {
       $fixnull = TRUE;
@@ -555,7 +559,7 @@ public function dropField($table, $field) {
 
     $this->connection->query('ALTER TABLE {' . $table . '} DROP COLUMN "' . $field . '"');
     $this->resetTableInformation($table);
-    return TRUE;
+    return parent::dropField($table, $field);
   }
 
   public function fieldSetDefault($table, $field, $default) {
@@ -678,6 +682,8 @@ public function changeField($table, $field, $field_new, $spec, $new_keys = array
       throw new SchemaObjectExistsException(t("Cannot rename field @table.@name to @name_new: target field already exists.", array('@table' => $table, '@name' => $field, '@name_new' => $field_new)));
     }
 
+    parent::changeField($table, $field, $field_new, $spec, $new_keys);
+
     $spec = $this->processField($spec);
 
     // Type 'serial' is known to PostgreSQL, but only during table creation,
diff --git a/core/lib/Drupal/Core/Database/Driver/sqlite/Schema.php b/core/lib/Drupal/Core/Database/Driver/sqlite/Schema.php
index 404cbb2..b8aec1e 100644
--- a/core/lib/Drupal/Core/Database/Driver/sqlite/Schema.php
+++ b/core/lib/Drupal/Core/Database/Driver/sqlite/Schema.php
@@ -257,6 +257,7 @@ public function renameTable($table, $new_name) {
       throw new SchemaObjectExistsException(t("Cannot rename @table to @table_new: table @table_new already exists.", array('@table' => $table, '@table_new' => $new_name)));
     }
 
+    parent::renameTable($table, $new_name);
     $schema = $this->introspectSchema($table);
 
     // SQLite doesn't allow you to rename tables outside of the current
@@ -292,7 +293,7 @@ public function dropTable($table) {
     }
     $this->connection->tableDropped = TRUE;
     $this->connection->query('DROP TABLE {' . $table . '}');
-    return TRUE;
+    return parent::dropTable($table);
   }
 
   public function addField($table, $field, $specification, $keys_new = array()) {
@@ -303,6 +304,8 @@ public function addField($table, $field, $specification, $keys_new = array()) {
       throw new SchemaObjectExistsException(t("Cannot add field @table.@field: field already exists.", array('@field' => $field, '@table' => $table)));
     }
 
+    parent::addField($table, $field, $specification, $keys_new);
+
     // SQLite doesn't have a full-featured ALTER TABLE statement. It only
     // supports adding new fields to a table, in some simple cases. In most
     // cases, we have to create a new table and copy the data over.
@@ -514,7 +517,7 @@ public function dropField($table, $field) {
       }
     }
     $this->alterTable($table, $old_schema, $new_schema);
-    return TRUE;
+    return parent::dropField($table, $field);
   }
 
   public function changeField($table, $field, $field_new, $spec, $keys_new = array()) {
@@ -525,6 +528,8 @@ public function changeField($table, $field, $field_new, $spec, $keys_new = array
       throw new SchemaObjectExistsException(t("Cannot rename field @table.@name to @name_new: target field already exists.", array('@table' => $table, '@name' => $field, '@name_new' => $field_new)));
     }
 
+    parent::changeField($table, $field, $field_new, $spec, $keys_new);
+
     $old_schema = $this->introspectSchema($table);
     $new_schema = $old_schema;
 
diff --git a/core/lib/Drupal/Core/Database/Schema.php b/core/lib/Drupal/Core/Database/Schema.php
index bd65330..67807c0 100644
--- a/core/lib/Drupal/Core/Database/Schema.php
+++ b/core/lib/Drupal/Core/Database/Schema.php
@@ -40,6 +40,13 @@
   protected $defaultSchema = 'public';
 
   /**
+   * The cache bin.
+   *
+   * @var \Drupal\Core\Cache\CacheBackendInterface
+   */
+  protected $cacheBin;
+
+  /**
    * A unique identifier for this query object.
    */
   protected $uniqueIdentifier;
@@ -47,6 +54,7 @@
   public function __construct($connection) {
     $this->uniqueIdentifier = uniqid('', TRUE);
     $this->connection = $connection;
+    $this->cacheBin = \Drupal::cache();
   }
 
   /**
@@ -284,7 +292,9 @@ public function fieldExists($table, $column) {
    * @throws \Drupal\Core\Database\SchemaObjectExistsException
    *   If a table with the specified new name already exists.
    */
-  abstract public function renameTable($table, $new_name);
+  public function renameTable($table, $new_name) {
+    $this->cacheBin->delete("table_mapping:$table");
+  }
 
   /**
    * Drop a table.
@@ -292,11 +302,14 @@ public function fieldExists($table, $column) {
    * @param $table
    *   The table to be dropped.
    *
-   * @return
+   * @return bool
    *   TRUE if the table was successfully dropped, FALSE if there was no table
    *   by that name to begin with.
    */
-  abstract public function dropTable($table);
+  public function dropTable($table) {
+    $this->cacheBin->delete("table_mapping:$table");
+    return TRUE;
+  }
 
   /**
    * Add a new field to a table.
@@ -324,7 +337,9 @@ public function fieldExists($table, $column) {
    * @throws \Drupal\Core\Database\SchemaObjectExistsException
    *   If the specified table already has a field by that name.
    */
-  abstract public function addField($table, $field, $spec, $keys_new = array());
+  public function addField($table, $field, $spec, $keys_new = array()) {
+    $this->cacheBin->delete("table_mapping:$table");
+  }
 
   /**
    * Drop a field.
@@ -334,11 +349,14 @@ public function fieldExists($table, $column) {
    * @param $field
    *   The field to be dropped.
    *
-   * @return
+   * @return bool
    *   TRUE if the field was successfully dropped, FALSE if there was no field
    *   by that name to begin with.
    */
-  abstract public function dropField($table, $field);
+  public function dropField($table, $field) {
+    $this->cacheBin->delete("table_mapping:$table");
+    return TRUE;
+  }
 
   /**
    * Set the default value for a field.
@@ -580,7 +598,9 @@ public function fieldExists($table, $column) {
    * @throws \Drupal\Core\Database\SchemaObjectExistsException
    *   If the specified destination field already exists.
    */
-  abstract public function changeField($table, $field, $field_new, $spec, $keys_new = array());
+  public function changeField($table, $field, $field_new, $spec, $keys_new = array()) {
+    $this->cacheBin->delete("table_mapping:$table");
+  }
 
   /**
    * Create a new table from a Drupal table definition.
diff --git a/core/lib/Drupal/Core/Entity/Query/Sql/Tables.php b/core/lib/Drupal/Core/Entity/Query/Sql/Tables.php
index e1a976a..5c112e6 100644
--- a/core/lib/Drupal/Core/Entity/Query/Sql/Tables.php
+++ b/core/lib/Drupal/Core/Entity/Query/Sql/Tables.php
@@ -7,6 +7,7 @@
 
 namespace Drupal\Core\Entity\Query\Sql;
 
+use Drupal\Core\Cache\Cache;
 use Drupal\Core\Database\Query\SelectInterface;
 use Drupal\Core\Entity\Query\QueryException;
 use Drupal\Core\Entity\Sql\SqlEntityStorageInterface;
@@ -41,6 +42,13 @@ class Tables implements TablesInterface {
   protected $fieldTables = array();
 
   /**
+   * The cache bin.
+   *
+   * @var \Drupal\Core\Cache\CacheBackendInterface
+   */
+  protected $cacheBin;
+
+  /**
    * The entity manager.
    *
    * @var \Drupal\Core\Entity\EntityManager
@@ -55,11 +63,19 @@ class Tables implements TablesInterface {
   protected $caseSensitiveFields = array();
 
   /**
+   * The table mappings.
+   *
+   * @var array[]
+   */
+  protected static $tableMapping;
+
+  /**
    * @param \Drupal\Core\Database\Query\SelectInterface $sql_query
    */
   public function __construct(SelectInterface $sql_query) {
     $this->sqlQuery = $sql_query;
     $this->entityManager = \Drupal::entityManager();
+    $this->cacheBin = \Drupal::cache();
   }
 
   /**
@@ -293,19 +309,32 @@ protected function addJoin($type, $table, $join_condition, $langcode) {
    *
    * @param string $table
    *   The table name.
+   * @param string $entity_type_id
+   *   The entity type id.
    *
    * @return array|bool
    *   The table field mapping for the given table or FALSE if not available.
    */
   protected function getTableMapping($table, $entity_type_id) {
-    $storage = $this->entityManager->getStorage($entity_type_id);
-    if ($storage instanceof SqlEntityStorageInterface) {
-      $mapping = $storage->getTableMapping()->getAllColumns($table);
-    }
-    else {
-      return FALSE;
+    if (!isset(static::$tableMapping[$table])) {
+      $cid = "table_mapping:$table";
+      if ($cache = $this->cacheBin->get($cid)) {
+        static::$tableMapping[$table] = $cache->data;
+      }
+      else {
+        $storage = $this->entityManager->getStorage($entity_type_id);
+        if ($storage instanceof SqlEntityStorageInterface) {
+          $mapping = array_flip($storage->getTableMapping()->getAllColumns($table));
+        }
+        else {
+          $mapping = FALSE;
+        }
+        $this->cacheBin->set($cid, $mapping);
+        static::$tableMapping[$table] = $mapping;
+      }
     }
-    return array_flip($mapping);
+
+    return static::$tableMapping[$table];
   }
 
 }
