diff --git a/core/lib/Drupal/Core/Entity/ContentEntityBase.php b/core/lib/Drupal/Core/Entity/ContentEntityBase.php
index e242544..8ffd51d 100644
--- a/core/lib/Drupal/Core/Entity/ContentEntityBase.php
+++ b/core/lib/Drupal/Core/Entity/ContentEntityBase.php
@@ -1188,22 +1188,26 @@ public static function baseFieldDefinitions(EntityTypeInterface $entity_type) {
       $fields[$entity_type->getKey('id')] = BaseFieldDefinition::create('integer')
         ->setLabel(new TranslatableMarkup('ID'))
         ->setReadOnly(TRUE)
+        ->setStorageRequired(TRUE)
         ->setSetting('unsigned', TRUE);
     }
     if ($entity_type->hasKey('uuid')) {
       $fields[$entity_type->getKey('uuid')] = BaseFieldDefinition::create('uuid')
         ->setLabel(new TranslatableMarkup('UUID'))
-        ->setReadOnly(TRUE);
+        ->setReadOnly(TRUE)
+        ->setStorageRequired(TRUE);
     }
     if ($entity_type->hasKey('revision')) {
       $fields[$entity_type->getKey('revision')] = BaseFieldDefinition::create('integer')
         ->setLabel(new TranslatableMarkup('Revision ID'))
         ->setReadOnly(TRUE)
+        ->setStorageRequired(TRUE)
         ->setSetting('unsigned', TRUE);
     }
     if ($entity_type->hasKey('langcode')) {
       $fields[$entity_type->getKey('langcode')] = BaseFieldDefinition::create('language')
         ->setLabel(new TranslatableMarkup('Language'))
+        ->setRequired(TRUE)
         ->setDisplayOptions('view', [
           'region' => 'hidden',
         ])
diff --git a/core/lib/Drupal/Core/Entity/EntityFieldManager.php b/core/lib/Drupal/Core/Entity/EntityFieldManager.php
index 5337288..92f47b4 100644
--- a/core/lib/Drupal/Core/Entity/EntityFieldManager.php
+++ b/core/lib/Drupal/Core/Entity/EntityFieldManager.php
@@ -216,7 +216,8 @@ protected function buildBaseFieldDefinitions($entity_type_id) {
           ->setDescription($this->t('A flag indicating whether this is the default translation.'))
           ->setTranslatable(TRUE)
           ->setRevisionable(TRUE)
-          ->setDefaultValue(TRUE);
+          ->setDefaultValue(TRUE)
+          ->setRequired(TRUE);
       }
     }
 
diff --git a/core/lib/Drupal/Core/Entity/EntityPublishedTrait.php b/core/lib/Drupal/Core/Entity/EntityPublishedTrait.php
index 871aceb..7b788ec 100644
--- a/core/lib/Drupal/Core/Entity/EntityPublishedTrait.php
+++ b/core/lib/Drupal/Core/Entity/EntityPublishedTrait.php
@@ -37,6 +37,7 @@ public static function publishedBaseFieldDefinitions(EntityTypeInterface $entity
       ->setDescription(new TranslatableMarkup('A boolean indicating the published state.'))
       ->setRevisionable(TRUE)
       ->setTranslatable(TRUE)
+      ->setRequired(TRUE)
       ->setDefaultValue(TRUE)];
   }
 
diff --git a/core/lib/Drupal/Core/Entity/Sql/SqlContentEntityStorageSchema.php b/core/lib/Drupal/Core/Entity/Sql/SqlContentEntityStorageSchema.php
index 96cea9f..b8fc149 100644
--- a/core/lib/Drupal/Core/Entity/Sql/SqlContentEntityStorageSchema.php
+++ b/core/lib/Drupal/Core/Entity/Sql/SqlContentEntityStorageSchema.php
@@ -12,6 +12,7 @@
 use Drupal\Core\Entity\EntityTypeInterface;
 use Drupal\Core\Entity\Exception\FieldStorageDefinitionUpdateForbiddenException;
 use Drupal\Core\Entity\Schema\DynamicallyFieldableEntityStorageSchemaInterface;
+use Drupal\Core\Field\BaseFieldDefinition;
 use Drupal\Core\Field\FieldException;
 use Drupal\Core\Field\FieldStorageDefinitionInterface;
 use Drupal\field\FieldStorageConfigInterface;
@@ -1048,11 +1049,7 @@ protected function processRevisionTable(ContentEntityTypeInterface $entity_type,
    * @return array
    *   A partial schema array for the base table.
    */
-  protected function processDataTable(ContentEntityTypeInterface $entity_type, array &$schema) {
-    // Marking the respective fields as NOT NULL makes the indexes more
-    // performant.
-    $schema['fields'][$entity_type->getKey('default_langcode')]['not null'] = TRUE;
-  }
+  protected function processDataTable(ContentEntityTypeInterface $entity_type, array &$schema) { }
 
   /**
    * Processes the gathered schema for a base table.
@@ -1065,11 +1062,7 @@ protected function processDataTable(ContentEntityTypeInterface $entity_type, arr
    * @return array
    *   A partial schema array for the base table.
    */
-  protected function processRevisionDataTable(ContentEntityTypeInterface $entity_type, array &$schema) {
-    // Marking the respective fields as NOT NULL makes the indexes more
-    // performant.
-    $schema['fields'][$entity_type->getKey('default_langcode')]['not null'] = TRUE;
-  }
+  protected function processRevisionDataTable(ContentEntityTypeInterface $entity_type, array &$schema) { }
 
   /**
    * Processes the specified entity key.
@@ -1607,35 +1600,40 @@ protected function getSharedTableFieldSchema(FieldStorageDefinitionInterface $st
     }
 
     $field_name = $storage_definition->getName();
-    $base_table = $this->storage->getBaseTable();
+    $properties = $storage_definition->getPropertyDefinitions();
+
+    $initial_value = [];
+    if ($storage_definition instanceof BaseFieldDefinition) {
+      if (($initial_storage_value = $storage_definition->getInitialValue()) && !empty($initial_storage_value))
+      $initial_value = $initial_value[0];
+    }
 
     // A shared table contains rows for entities where the field is empty
     // (since other fields stored in the same table might not be empty), thus
     // the only columns that can be 'not null' are those for required
-    // properties of required fields. However, even those would break in the
-    // case where a new field is added to a table that contains existing rows.
-    // For now, we only hardcode 'not null' to a couple "entity keys", in order
-    // to keep their indexes optimized.
-    // @todo Revisit once we have support for 'initial' in
-    //   https://www.drupal.org/node/2346019.
-    $not_null_keys = $this->entityType->getKeys();
-    // Label fields are not necessarily required.
-    unset($not_null_keys['label']);
+    // properties of required fields.
+    $field_storage_is_required = $storage_definition->isStorageRequired();
+
     // Because entity ID and revision ID are both serial fields in the base and
     // revision table respectively, the revision ID is not known yet, when
     // inserting data into the base table. Instead the revision ID in the base
     // table is updated after the data has been inserted into the revision
     // table. For this reason the revision ID field cannot be marked as NOT
     // NULL.
-    if ($table_name == $base_table) {
-      unset($not_null_keys['revision']);
+    if ($table_name == $this->storage->getBaseTable() && $field_name == $this->entityType->getKey('revision')) {
+      $field_storage_is_required = FALSE;
     }
 
     foreach ($column_mapping as $field_column_name => $schema_field_name) {
       $column_schema = $field_schema['columns'][$field_column_name];
 
       $schema['fields'][$schema_field_name] = $column_schema;
-      $schema['fields'][$schema_field_name]['not null'] = in_array($field_name, $not_null_keys);
+      $schema['fields'][$schema_field_name]['not null'] = $field_storage_is_required && $properties[$field_column_name]->isRequired();
+
+      // Use the initial value of the field storage, if available.
+      if ($initial_value && isset($initial_value[$field_column_name])) {
+        $schema['fields'][$schema_field_name]['initial'] = $initial_value[$field_column_name];
+      }
     }
 
     if (!empty($field_schema['indexes'])) {
diff --git a/core/lib/Drupal/Core/Field/BaseFieldDefinition.php b/core/lib/Drupal/Core/Field/BaseFieldDefinition.php
index e28d997..c478d2b 100644
--- a/core/lib/Drupal/Core/Field/BaseFieldDefinition.php
+++ b/core/lib/Drupal/Core/Field/BaseFieldDefinition.php
@@ -12,7 +12,7 @@
 /**
  * A class for defining entity fields.
  */
-class BaseFieldDefinition extends ListDataDefinition implements FieldDefinitionInterface, FieldStorageDefinitionInterface {
+class BaseFieldDefinition extends ListDataDefinition implements FieldDefinitionInterface, FieldStorageDefinitionInterface, RequiredFieldStorageDefinitionInterface {
 
   use UnchangingCacheableDependencyTrait;
 
@@ -503,6 +503,39 @@ public function setDefaultValueCallback($callback) {
     return $this;
   }
 
+  public function getInitialValue() {
+    $value = isset($this->definition['initial_value']) ? $this->definition['initial_value'] : [];
+
+    // Normalize into the "array keyed by delta" format.
+    if (isset($value) && !is_array($value)) {
+      $properties = $this->getPropertyNames();
+      $property = reset($properties);
+      $value = array(
+        array($property => $value),
+      );
+    }
+
+    return $value;
+  }
+
+  public function setInitialValue($value) {
+    if ($value === NULL) {
+      $value = [];
+    }
+    // Unless the value is an empty array, we may need to transform it.
+    if (!is_array($value) || !empty($value)) {
+      if (!is_array($value)) {
+        $value = array(array($this->getMainPropertyName() => $value));
+      }
+      elseif (is_array($value) && !is_numeric(array_keys($value)[0])) {
+        $value = array(0 => $value);
+      }
+    }
+    $this->definition['initial_value'] = $value;
+
+    return $this;
+  }
+
   /**
    * {@inheritdoc}
    */
@@ -723,4 +756,30 @@ public function getConfig($bundle) {
     return BaseFieldOverride::createFromBaseFieldDefinition($this, $bundle);
   }
 
+  /**
+   * {@inheritdoc}
+   */
+  public function isStorageRequired() {
+    if (isset($this->definition['storage_required'])) {
+      return (bool) $this->definition['storage_required'];
+    }
+
+    // Default to the 'required' property of the base field.
+    return $this->isRequired();
+  }
+
+  /**
+   * Sets whether the field storage is required.
+   *
+   * @param bool $required
+   *   Whether the field storage is required.
+   *
+   * @return static
+   *   The object itself for chaining.
+   */
+  public function setStorageRequired($required) {
+    $this->definition['storage_required'] = $required;
+    return $this;
+  }
+
 }
diff --git a/core/lib/Drupal/Core/Field/Plugin/Field/FieldType/LanguageItem.php b/core/lib/Drupal/Core/Field/Plugin/Field/FieldType/LanguageItem.php
index 0b9bba9..e5f3f08 100644
--- a/core/lib/Drupal/Core/Field/Plugin/Field/FieldType/LanguageItem.php
+++ b/core/lib/Drupal/Core/Field/Plugin/Field/FieldType/LanguageItem.php
@@ -2,6 +2,7 @@
 
 namespace Drupal\Core\Field\Plugin\Field\FieldType;
 
+use Drupal\Core\Field\FieldDefinitionInterface;
 use Drupal\Core\Field\FieldStorageDefinitionInterface;
 use Drupal\Core\Field\FieldItemBase;
 use Drupal\Core\Language\LanguageInterface;
@@ -117,4 +118,12 @@ public function onChange($property_name, $notify = TRUE) {
     parent::onChange($property_name, $notify);
   }
 
+  /**
+   * {@inheritdoc}
+   */
+  public static function generateSampleValue(FieldDefinitionInterface $field_definition) {
+    $values['value'] = LanguageInterface::LANGCODE_NOT_SPECIFIED;
+    return $values;
+  }
+
 }
diff --git a/core/lib/Drupal/Core/Field/RequiredFieldStorageDefinitionInterface.php b/core/lib/Drupal/Core/Field/RequiredFieldStorageDefinitionInterface.php
new file mode 100644
index 0000000..d29e569
--- /dev/null
+++ b/core/lib/Drupal/Core/Field/RequiredFieldStorageDefinitionInterface.php
@@ -0,0 +1,21 @@
+<?php
+
+namespace Drupal\Core\Field;
+
+/**
+ * Defines an interface for required field storage definitions.
+ */
+interface RequiredFieldStorageDefinitionInterface {
+
+  /**
+   * Returns whether the field storage is required.
+   *
+   * If a field storage is required, NOT NULL constraints will be added
+   * automatically for the required properties of a field type.
+   *
+   * @return bool
+   *   TRUE if the field storage is required, FALSE otherwise.
+   */
+  public function isStorageRequired();
+
+}
diff --git a/core/modules/aggregator/src/Tests/FeedParserTest.php b/core/modules/aggregator/src/Tests/FeedParserTest.php
index 6c4a04d..128ea83 100644
--- a/core/modules/aggregator/src/Tests/FeedParserTest.php
+++ b/core/modules/aggregator/src/Tests/FeedParserTest.php
@@ -85,7 +85,7 @@ public function testHtmlEntitiesSample() {
    */
   public function testRedirectFeed() {
     $redirect_url = Url::fromRoute('aggregator_test.redirect')->setAbsolute()->toString();
-    $feed = Feed::create(array('url' => $redirect_url, 'title' => $this->randomMachineName()));
+    $feed = Feed::create(array('url' => $redirect_url, 'title' => $this->randomMachineName(), 'refresh' => 900));
     $feed->save();
     $feed->refreshItems();
 
@@ -99,7 +99,7 @@ public function testRedirectFeed() {
   public function testInvalidFeed() {
     // Simulate a typo in the URL to force a curl exception.
     $invalid_url = 'http:/www.drupal.org';
-    $feed = Feed::create(array('url' => $invalid_url, 'title' => $this->randomMachineName()));
+    $feed = Feed::create(array('url' => $invalid_url, 'title' => $this->randomMachineName(), 'refresh' => 900));
     $feed->save();
 
     // Update the feed. Use the UI to be able to check the message easily.
diff --git a/core/modules/aggregator/tests/src/Kernel/Views/AggregatorFeedViewsFieldAccessTest.php b/core/modules/aggregator/tests/src/Kernel/Views/AggregatorFeedViewsFieldAccessTest.php
index d0ca46e..9fa4496 100644
--- a/core/modules/aggregator/tests/src/Kernel/Views/AggregatorFeedViewsFieldAccessTest.php
+++ b/core/modules/aggregator/tests/src/Kernel/Views/AggregatorFeedViewsFieldAccessTest.php
@@ -34,6 +34,7 @@ public function testAggregatorFeedFields() {
       'title' => 'Drupal org',
       'url' => 'https://www.drupal.org/rss.xml',
       'link' => 'https://www.drupal.org/rss.xml',
+      'refresh' => 900,
     ]);
     $feed->save();
 
diff --git a/core/modules/comment/tests/src/Kernel/Views/CommentLinksTest.php b/core/modules/comment/tests/src/Kernel/Views/CommentLinksTest.php
index ffb91b0..08a326d 100644
--- a/core/modules/comment/tests/src/Kernel/Views/CommentLinksTest.php
+++ b/core/modules/comment/tests/src/Kernel/Views/CommentLinksTest.php
@@ -19,6 +19,13 @@
 class CommentLinksTest extends CommentViewsKernelTestBase {
 
   /**
+   * Modules to enable.
+   *
+   * @var array
+   */
+  public static $modules = ['entity_test'];
+
+  /**
    * Views used by this test.
    *
    * @var array
@@ -26,14 +33,26 @@ class CommentLinksTest extends CommentViewsKernelTestBase {
   public static $testViews = ['test_comment'];
 
   /**
+   * {@inheritdoc}
+   */
+  protected function setUp($import_test_views = TRUE) {
+    parent::setUp($import_test_views);
+
+    $this->installEntitySchema('entity_test');
+  }
+
+  /**
    * Test the comment approve link.
    */
   public function testLinkApprove() {
+    $host = EntityTest::create(['name' => $this->randomString()]);
+    $host->save();
 
     // Create an unapproved comment.
     $comment = $this->commentStorage->create([
       'uid' => $this->adminUser->id(),
       'entity_type' => 'entity_test',
+      'entity_id' => $host->id(),
       'comment_type' => 'entity_test',
       'status' => 0,
     ]);
@@ -91,8 +110,7 @@ public function testLinkApprove() {
    * Test the comment reply link.
    */
   public function testLinkReply() {
-    $this->enableModules(['field', 'entity_test']);
-    $this->installEntitySchema('entity_test');
+    $this->enableModules(['field']);
     $this->installSchema('comment', ['comment_entity_statistics']);
     $this->installConfig(['field']);
 
diff --git a/core/modules/comment/tests/src/Kernel/Views/CommentUserNameTest.php b/core/modules/comment/tests/src/Kernel/Views/CommentUserNameTest.php
index dae2c48..92112e4 100644
--- a/core/modules/comment/tests/src/Kernel/Views/CommentUserNameTest.php
+++ b/core/modules/comment/tests/src/Kernel/Views/CommentUserNameTest.php
@@ -4,6 +4,7 @@
 
 use Drupal\comment\Entity\Comment;
 use Drupal\Core\Session\AnonymousUserSession;
+use Drupal\entity_test\Entity\EntityTest;
 use Drupal\Tests\views\Kernel\ViewsKernelTestBase;
 use Drupal\user\Entity\Role;
 use Drupal\user\Entity\User;
@@ -36,6 +37,7 @@ protected function setUp($import_test_views = TRUE) {
 
     $this->installEntitySchema('user');
     $this->installEntitySchema('comment');
+    $this->installEntitySchema('entity_test');
     // Create the anonymous role.
     $this->installConfig(['user']);
 
@@ -67,12 +69,16 @@ protected function setUp($import_test_views = TRUE) {
     ]);
     $this->adminUser->save();
 
+    $host = EntityTest::create(['name' => $this->randomString()]);
+    $host->save();
+
     // Create some comments.
     $comment = Comment::create([
       'subject' => 'My comment title',
       'uid' => $this->adminUser->id(),
       'name' => $this->adminUser->label(),
       'entity_type' => 'entity_test',
+      'entity_id' => $host->id(),
       'comment_type' => 'entity_test',
       'status' => 1,
     ]);
@@ -85,6 +91,7 @@ protected function setUp($import_test_views = TRUE) {
       'mail' => 'test@example.com',
       'homepage' => 'https://example.com',
       'entity_type' => 'entity_test',
+      'entity_id' => $host->id(),
       'comment_type' => 'entity_test',
       'created' => 123456,
       'status' => 1,
diff --git a/core/modules/comment/tests/src/Kernel/Views/CommentViewsFieldAccessTest.php b/core/modules/comment/tests/src/Kernel/Views/CommentViewsFieldAccessTest.php
index f807c58..1ca5e43 100644
--- a/core/modules/comment/tests/src/Kernel/Views/CommentViewsFieldAccessTest.php
+++ b/core/modules/comment/tests/src/Kernel/Views/CommentViewsFieldAccessTest.php
@@ -3,6 +3,7 @@
 namespace Drupal\Tests\comment\Kernel\Views;
 
 use Drupal\comment\Entity\Comment;
+use Drupal\entity_test\Entity\EntityTest;
 use Drupal\user\Entity\User;
 use Drupal\Tests\views\Kernel\Handler\FieldFieldAccessTestBase;
 
@@ -25,6 +26,7 @@ protected function setUp($import_test_views = TRUE) {
     parent::setUp($import_test_views);
 
     $this->installEntitySchema('comment');
+    $this->installEntitySchema('entity_test');
   }
 
   /**
@@ -36,10 +38,14 @@ public function testCommentFields() {
     ]);
     $user->save();
 
+    $host = EntityTest::create(['name' => $this->randomString()]);
+    $host->save();
+
     $comment = Comment::create([
       'subject' => 'My comment title',
       'uid' => $user->id(),
       'entity_type' => 'entity_test',
+      'entity_id' => $host->id(),
       'comment_type' => 'entity_test',
     ]);
     $comment->save();
@@ -51,6 +57,7 @@ public function testCommentFields() {
       'mail' => 'test@example.com',
       'homepage' => 'https://example.com',
       'entity_type' => 'entity_test',
+      'entity_id' => $host->id(),
       'comment_type' => 'entity_test',
       'created' => 123456,
       'status' => 1,
diff --git a/core/tests/Drupal/Tests/Core/Entity/BaseFieldDefinitionTest.php b/core/tests/Drupal/Tests/Core/Entity/BaseFieldDefinitionTest.php
index dbd50e7..bb46683 100644
--- a/core/tests/Drupal/Tests/Core/Entity/BaseFieldDefinitionTest.php
+++ b/core/tests/Drupal/Tests/Core/Entity/BaseFieldDefinitionTest.php
@@ -255,6 +255,21 @@ public function testFieldRequired() {
   }
 
   /**
+   * Tests storage required.
+   *
+   * @covers ::isStorageRequired
+   * @covers ::setStorageRequired
+   */
+  public function testFieldStorageRequired() {
+    $definition = BaseFieldDefinition::create($this->fieldType);
+    $this->assertFalse($definition->isStorageRequired());
+    $definition->setStorageRequired(TRUE);
+    $this->assertTrue($definition->isStorageRequired());
+    $definition->setStorageRequired(FALSE);
+    $this->assertFalse($definition->isStorageRequired());
+  }
+
+  /**
    * Tests provider.
    *
    * @covers ::getProvider
