diff --git a/core/lib/Drupal/Core/Entity/ContentEntityStorageBase.php b/core/lib/Drupal/Core/Entity/ContentEntityStorageBase.php
index acc17ba..4a730d1 100644
--- a/core/lib/Drupal/Core/Entity/ContentEntityStorageBase.php
+++ b/core/lib/Drupal/Core/Entity/ContentEntityStorageBase.php
@@ -206,4 +206,43 @@ protected function invokeFieldMethod($method, ContentEntityInterface $entity) {
     }
   }
 
+  /**
+   * Checks whether the field values changed compared to the original entity.
+   *
+   * @param \Drupal\Core\Field\FieldDefinitionInterface $field_definition
+   *   Field definition of field to compare for changes.
+   * @param \Drupal\Core\Entity\ContentEntityInterface $entity
+   *   Entity to check for field changes.
+   * @param \Drupal\Core\Entity\ContentEntityInterface $original
+   *   Original entity to compare against.
+   *
+   * @return bool
+   *   True if the field value changed from the original entity.
+   */
+  protected function hasFieldValueChanged(FieldDefinitionInterface $field_definition, ContentEntityInterface $entity, ContentEntityInterface $original) {
+    $field_name = $field_definition->getName();
+    if ($field_definition->isTranslatable()) {
+      $langcodes = array_keys($entity->getTranslationLanguages());
+    }
+    else {
+      $langcodes = [$entity->getUntranslated()->language()->getId()];
+    }
+
+    foreach ($langcodes as $langcode) {
+      // If the original entity doesn't have this translation, we need to save.
+      if (!$original->hasTranslation($langcode)) {
+        return TRUE;
+      }
+
+      $items = $entity->getTranslation($langcode)->get($field_name)->filterEmptyItems();
+      $originalItems = $original->getTranslation($langcode)->get($field_name)->filterEmptyItems();
+      // If the field items are not equal, we need to save.
+      if (!$items->equals($originalItems)) {
+        return TRUE;
+      }
+    }
+
+    return FALSE;
+  }
+
 }
diff --git a/core/lib/Drupal/Core/Entity/Sql/SqlContentEntityStorage.php b/core/lib/Drupal/Core/Entity/Sql/SqlContentEntityStorage.php
index 22d2f92..30dd4a7 100644
--- a/core/lib/Drupal/Core/Entity/Sql/SqlContentEntityStorage.php
+++ b/core/lib/Drupal/Core/Entity/Sql/SqlContentEntityStorage.php
@@ -22,6 +22,7 @@
 use Drupal\Core\Entity\Query\QueryInterface;
 use Drupal\Core\Entity\Schema\DynamicallyFieldableEntityStorageSchemaInterface;
 use Drupal\Core\Field\FieldDefinitionInterface;
+use Drupal\Core\Field\FieldItemListInterface;
 use Drupal\Core\Field\FieldStorageDefinitionInterface;
 use Drupal\Core\Language\LanguageInterface;
 use Drupal\field\FieldStorageConfigInterface;
@@ -1317,11 +1318,21 @@ protected function saveToDedicatedTables(ContentEntityInterface $entity, $update
       $vid = $id;
     }
 
+    $original = !empty($entity->original) ? $entity->original: NULL;
+
     foreach ($this->entityManager->getFieldDefinitions($entity_type, $bundle) as $field_name => $field_definition) {
       $storage_definition = $field_definition->getFieldStorageDefinition();
       if (!$table_mapping->requiresDedicatedTableStorage($storage_definition)) {
         continue;
       }
+
+      // Check if the given entity is a new revision or not. In case of a new
+      // revision creation, we cannot skip any field else the new revision
+      // would be empty.
+      if ($original && $vid == $original->getRevisionId() && !$this->hasFieldValueChanged($field_definition, $entity, $original)) {
+        continue;
+      }
+
       $table_name = $table_mapping->getDedicatedDataTableName($storage_definition);
       $revision_name = $table_mapping->getDedicatedRevisionTableName($storage_definition);
 
diff --git a/core/lib/Drupal/Core/Field/FieldItemList.php b/core/lib/Drupal/Core/Field/FieldItemList.php
index 930b4e1..86bac79 100644
--- a/core/lib/Drupal/Core/Field/FieldItemList.php
+++ b/core/lib/Drupal/Core/Field/FieldItemList.php
@@ -98,6 +98,7 @@ public function filterEmptyItems() {
     $this->filter(function ($item) {
       return !$item->isEmpty();
     });
+    return $this;
   }
 
   /**
@@ -370,4 +371,38 @@ protected function defaultValueWidget(FormStateInterface $form_state) {
     return $form_state->get('default_value_widget');
   }
 
+  /**
+   * {@inheritdoc}
+   */
+  public function equals(FieldItemListInterface $list_to_compare) {
+    $columns = $this->getFieldDefinition()->getFieldStorageDefinition()->getColumns();
+    $count1 = count($this);
+    $count2 = count($list_to_compare);
+    if ($count1 === 0 && $count2 === 0) {
+      // Both are empty we can safely assume that it did not change.
+      return TRUE;
+    }
+    if ($count1 !== $count2) {
+      // One of them is empty but not the other one so the value changed.
+      return FALSE;
+    }
+    $value1 = $this->getValue();
+    $value2 = $list_to_compare->getValue();
+    if ($value1 === $value2) {
+      return TRUE;
+    }
+    // If the values are not equal ensure a consistent order of field item
+    // properties and remove properties which will not be saved.
+    $callback = function (&$value) use ($columns) {
+      if (is_array($value)) {
+        $value = array_intersect_key($value, $columns);
+        ksort($value);
+      }
+    };
+    array_walk($value1, $callback);
+    array_walk($value2, $callback);
+
+    return $value1 === $value2;
+  }
+
 }
diff --git a/core/lib/Drupal/Core/Field/FieldItemListInterface.php b/core/lib/Drupal/Core/Field/FieldItemListInterface.php
index aeb6005..e4ea12c 100644
--- a/core/lib/Drupal/Core/Field/FieldItemListInterface.php
+++ b/core/lib/Drupal/Core/Field/FieldItemListInterface.php
@@ -94,6 +94,8 @@ public function defaultAccess($operation = 'view', AccountInterface $account = N
 
   /**
    * Filters out empty field items and re-numbers the item deltas.
+   *
+   * @return $this
    */
   public function filterEmptyItems();
 
@@ -258,4 +260,15 @@ public function defaultValuesFormSubmit(array $element, array &$form, FormStateI
    */
   public static function processDefaultValue($default_value, FieldableEntityInterface $entity, FieldDefinitionInterface $definition);
 
+  /**
+   * Determines equality to another object implementing FieldItemListInterface.
+   *
+   * @param \Drupal\Core\Field\FieldItemListInterface $list_to_compare
+   *   The field item list to compare to.
+   *
+   * @return bool
+   *   TRUE if the field item lists are equal, FALSE if not.
+   */
+  public function equals(FieldItemListInterface $list_to_compare);
+
 }
diff --git a/core/tests/Drupal/Tests/Core/Field/FieldItemListTest.php b/core/tests/Drupal/Tests/Core/Field/FieldItemListTest.php
new file mode 100644
index 0000000..65e996e
--- /dev/null
+++ b/core/tests/Drupal/Tests/Core/Field/FieldItemListTest.php
@@ -0,0 +1,149 @@
+<?php
+
+/**
+ * @file Contains \Drupal\Tests\Core\Field\FieldItemListTest.
+ */
+
+namespace Drupal\Tests\Core\Field;
+
+use Drupal\Core\DependencyInjection\ContainerBuilder;
+use Drupal\Core\Field\FieldItemInterface;
+use Drupal\Core\Field\FieldItemList;
+use Drupal\Tests\UnitTestCase;
+
+/**
+ * @coversDefaultClass \Drupal\Core\Field\FieldItemList
+ * @group Field
+ */
+class FieldItemListTest extends UnitTestCase {
+
+  /**
+   * @covers ::equals
+   *
+   * @dataProvider providerTestEquals
+   */
+  public function testEquals($expected, FieldItemInterface $first_field_item = NULL, FieldItemInterface $second_field_item = NULL) {
+
+    // Mock the field type manager and place it in the container.
+    $field_type_manager = $this->getMock('Drupal\Core\Field\FieldTypePluginManagerInterface');
+    $container = new ContainerBuilder();
+    $container->set('plugin.manager.field.field_type', $field_type_manager);
+    \Drupal::setContainer($container);
+
+    $field_storage_definition = $this->getMock('Drupal\Core\Field\FieldStorageDefinitionInterface');
+    $field_storage_definition->expects($this->any())
+      ->method('getColumns')
+      ->willReturn([0 => '0', 1 => '1']);
+    $field_definition = $this->getMock('Drupal\Core\Field\FieldDefinitionInterface');
+    $field_definition->expects($this->any())
+      ->method('getFieldStorageDefinition')
+      ->willReturn($field_storage_definition);
+
+    $field_list_a = new FieldItemList($field_definition);
+    $field_list_b = new FieldItemList($field_definition);
+
+    // Set up the mocking necessary for creating field items.
+    $field_type_manager->expects($this->any())
+      ->method('createFieldItem')
+      ->willReturnOnConsecutiveCalls($first_field_item, $second_field_item);
+
+    // Set the field item values.
+    if ($first_field_item instanceof FieldItemInterface) {
+      $field_list_a->setValue($first_field_item);
+    }
+    if ($second_field_item instanceof FieldItemInterface) {
+      $field_list_b->setValue($second_field_item);
+    }
+
+    $this->assertEquals($expected, $field_list_a->equals($field_list_b));
+  }
+
+  /**
+   * Data provider for testEquals.
+   */
+  public function providerTestEquals() {
+    // Tests field item lists with no values.
+    $datasets[] = [TRUE];
+
+    /** @var \Drupal\Core\Field\FieldItemBase  $field_item_a */
+    $field_item_a = $this->getMockForAbstractClass('Drupal\Core\Field\FieldItemBase', [], '', FALSE);
+    $field_item_a->setValue([1]);
+    // Tests field item lists where one has a value and one does not.
+    $datasets[] = [FALSE, $field_item_a];
+
+    // Tests field item lists where both have the same value.
+    $datasets[] = [TRUE, $field_item_a, $field_item_a];
+
+    /** @var \Drupal\Core\Field\FieldItemBase  $fv */
+    $field_item_b = $this->getMockForAbstractClass('Drupal\Core\Field\FieldItemBase', [], '', FALSE);
+    $field_item_b->setValue([2]);
+    // Tests field item lists where both have the different values.
+    $datasets[] = [FALSE, $field_item_a, $field_item_b];
+
+    /** @var \Drupal\Core\Field\FieldItemBase  $fv */
+    $field_item_c = $this->getMockForAbstractClass('Drupal\Core\Field\FieldItemBase', [], '', FALSE);
+    $field_item_c->setValue(['0' => 1, '1' => 2]);
+    $field_item_d = $this->getMockForAbstractClass('Drupal\Core\Field\FieldItemBase', [], '', FALSE);
+    $field_item_d->setValue(['1' => 2, '0' => 1]);
+
+    // Tests field item lists where both have the differently ordered values.
+    $datasets[] = [TRUE, $field_item_c, $field_item_d];
+
+    return $datasets;
+  }
+
+  /**
+   * @covers ::equals
+   */
+  public function testEqualsEmptyItems() {
+    /** @var \Drupal\Core\Field\FieldItemBase  $fv */
+    $first_field_item = $this->getMockForAbstractClass('Drupal\Core\Field\FieldItemBase', [], '', FALSE);
+    $first_field_item->setValue(['0' => 1, '1' => 2]);
+    $second_field_item = $this->getMockForAbstractClass('Drupal\Core\Field\FieldItemBase', [], '', FALSE);
+    $second_field_item->setValue(['1' => 2, '0' => 1]);
+    $empty_field_item = $this->getMockForAbstractClass('Drupal\Core\Field\FieldItemBase', [], '', FALSE);
+    // Mock the field type manager and place it in the container.
+    $field_type_manager = $this->getMock('Drupal\Core\Field\FieldTypePluginManagerInterface');
+    $container = new ContainerBuilder();
+    $container->set('plugin.manager.field.field_type', $field_type_manager);
+    \Drupal::setContainer($container);
+
+    $field_storage_definition = $this->getMock('Drupal\Core\Field\FieldStorageDefinitionInterface');
+    $field_storage_definition->expects($this->any())
+      ->method('getColumns')
+      ->willReturn([0 => '0', 1 => '1']);
+    $field_definition = $this->getMock('Drupal\Core\Field\FieldDefinitionInterface');
+    $field_definition->expects($this->any())
+      ->method('getFieldStorageDefinition')
+      ->willReturn($field_storage_definition);
+
+    $field_list_a = new FieldItemList($field_definition);
+    $field_list_b = new FieldItemList($field_definition);
+
+    // Set up the mocking necessary for creating field items.
+    $field_type_manager->expects($this->any())
+      ->method('createFieldItem')
+      ->willReturnOnConsecutiveCalls($first_field_item, $second_field_item, $empty_field_item, $empty_field_item);
+
+    // Set the field item values.
+    $field_list_a->setValue($first_field_item);
+    $field_list_b->setValue($second_field_item);
+    $field_list_a->appendItem($empty_field_item);
+
+    // Field list A has an empty item.
+    $this->assertEquals(FALSE, $field_list_a->equals($field_list_b));
+
+    // Field lists A and B have empty items.
+    $field_list_b->appendItem($empty_field_item);
+    $this->assertEquals(TRUE, $field_list_a->equals($field_list_b));
+
+    // Field list B has an empty item.
+    $field_list_a->filterEmptyItems();
+    $this->assertEquals(FALSE, $field_list_a->equals($field_list_b));
+
+    // Neither field lists A and B have empty items.
+    $field_list_b->filterEmptyItems();
+    $this->assertEquals(TRUE, $field_list_a->equals($field_list_b));
+  }
+
+}
