diff --git a/schemadotorg.services.yml b/schemadotorg.services.yml
index d6af1100764bdff2279906c60801c623a7b28c27..2e7202d5dc2412b6b7bd49ee1238aef5cff17bdd 100644
--- a/schemadotorg.services.yml
+++ b/schemadotorg.services.yml
@@ -10,7 +10,7 @@ services:
     arguments: ['@config.factory', '@config.typed', '@entity_type.manager', '@schemadotorg.schema_type_manager']
   schemadotorg.schema_type_manager:
     class: Drupal\schemadotorg\SchemaDotOrgSchemaTypeManager
-    arguments: ['@database', '@schemadotorg.names']
+    arguments: ['@database', '@cache.data', '@schemadotorg.names']
   schemadotorg.schema_type_builder:
     class: Drupal\schemadotorg\SchemaDotOrgSchemaTypeBuilder
     arguments: ['@module_handler', '@current_user', '@schemadotorg.schema_type_manager']
diff --git a/src/Plugin/EntityReferenceSelection/SchemaDotOrgEntityReferenceSelection.php b/src/Plugin/EntityReferenceSelection/SchemaDotOrgEntityReferenceSelection.php
index e70b838905a628c7b3fb9c37a650ac79e9fc5e97..3e127370d81c5a9bc63114314bb0a1af32b4ae9a 100644
--- a/src/Plugin/EntityReferenceSelection/SchemaDotOrgEntityReferenceSelection.php
+++ b/src/Plugin/EntityReferenceSelection/SchemaDotOrgEntityReferenceSelection.php
@@ -5,6 +5,7 @@ declare(strict_types=1);
 namespace Drupal\schemadotorg\Plugin\EntityReferenceSelection;
 
 use Drupal\Component\Utility\Html;
+use Drupal\Core\Config\Entity\ConfigEntityStorageInterface;
 use Drupal\Core\Entity\EntityInterface;
 use Drupal\Core\Entity\EntityReferenceSelection\SelectionPluginBase;
 use Drupal\Core\Entity\EntityRepositoryInterface;
@@ -59,7 +60,7 @@ class SchemaDotOrgEntityReferenceSelection extends SelectionPluginBase implement
   /**
    * The mapping storage.
    */
-  protected SchemaDotOrgMappingStorageInterface $mappingStorage;
+  protected SchemaDotOrgMappingStorageInterface|ConfigEntityStorageInterface $mappingStorage;
 
   /**
    * The entity repository.
diff --git a/src/SchemaDotOrgSchemaTypeManager.php b/src/SchemaDotOrgSchemaTypeManager.php
index 2e796adfc11c78c92240f00a1e721eb82466c09f..b5d2a52d3cc9e1dc77b8eac54621d12b6b4ce55b 100644
--- a/src/SchemaDotOrgSchemaTypeManager.php
+++ b/src/SchemaDotOrgSchemaTypeManager.php
@@ -4,6 +4,7 @@ declare(strict_types=1);
 
 namespace Drupal\schemadotorg;
 
+use Drupal\Core\Cache\CacheBackendInterface;
 use Drupal\Core\Database\Connection;
 use Drupal\Core\StringTranslation\StringTranslationTrait;
 use Drupal\Core\StringTranslation\TranslatableMarkup;
@@ -33,21 +34,19 @@ class SchemaDotOrgSchemaTypeManager implements SchemaDotOrgSchemaTypeManagerInte
    */
   protected array $itemsCache = [];
 
-  /**
-   * Schema.org superseded cache.
-   */
-  protected array $supersededCache;
-
   /**
    * Constructs a SchemaDotOrgSchemaTypeManager object.
    *
    * @param \Drupal\Core\Database\Connection $database
    *   The database connection.
+   * @param \Drupal\Core\Cache\CacheBackendInterface $cacheBackend
+   *   Cache backend instance to use.
    * @param \Drupal\schemadotorg\SchemaDotOrgNamesInterface $schemaNames
    *   The Schema.org names service.
    */
   public function __construct(
     protected Connection $database,
+    protected CacheBackendInterface $cacheBackend,
     protected SchemaDotOrgNamesInterface $schemaNames
   ) {}
 
@@ -58,32 +57,141 @@ class SchemaDotOrgSchemaTypeManager implements SchemaDotOrgSchemaTypeManagerInte
     return static::URI . $id;
   }
 
+  /**
+   * Get information about Schema.org types and properties.
+   *
+   * @return array
+   *   An associative array keyed by ids containing
+   *   information about Schema.org types and properties.
+   */
+  protected function getInfo(): array {
+    if ($cache = $this->cacheBackend->get('schemadotorg_info')) {
+      return $cache->data;
+    }
+
+    $info = [
+      static::SCHEMA_TYPES => [],
+      static::SCHEMA_PROPERTIES => [],
+    ];
+
+    // Types.
+    $result = $this->database->select('schemadotorg_types', 't')
+      ->fields('t', ['id', 'enumerationtype', 'properties', 'superseded_by', 'sub_type_of'])
+      ->orderBy('id')
+      ->execute();
+    $types = [];
+    while ($record = $result->fetchAssoc()) {
+      $id = str_replace('https://schema.org/', '', $record['id']);
+      $types[$id] = $record;
+
+      $info[self::SCHEMA_TYPES][$id] = [];
+
+      // Superseded.
+      if (!empty($record['superseded_by'])) {
+        $info[self::SCHEMA_TYPES][$id][static::SCHEMA_SUPERSEDED] = TRUE;
+      }
+
+      $breadcrumbs = $this->getTypeBreadcrumbs($id);
+      foreach ($breadcrumbs as $breadcrumb => $items) {
+        // Enumeration.
+        if (str_starts_with($breadcrumb, 'Thing/Intangible/Enumeration')) {
+          $info[self::SCHEMA_TYPES][$id][static::SCHEMA_INTANGIBLE] = TRUE;
+          $info[self::SCHEMA_TYPES][$id][static::SCHEMA_ENUMERATION] = TRUE;
+          if ($record['enumerationtype']) {
+            $info[self::SCHEMA_TYPES][$id][static::SCHEMA_ENUMERATION_VALUE] = TRUE;
+          }
+          else {
+            $info[self::SCHEMA_TYPES][$id][static::SCHEMA_ENUMERATION_TYPE] = TRUE;
+          }
+        }
+        // Intangible.
+        elseif (str_starts_with($breadcrumb, 'Thing/Intangible')) {
+          $info[self::SCHEMA_TYPES][$id][static::SCHEMA_INTANGIBLE] = TRUE;
+        }
+        // Thing.
+        elseif (str_starts_with($breadcrumb, 'Thing')) {
+          if (!empty($record['properties'])) {
+            $info[self::SCHEMA_TYPES][$id][static::SCHEMA_THING] = TRUE;
+          }
+        }
+        // Data type.
+        else {
+          $info[self::SCHEMA_TYPES][$id][static::SCHEMA_DATA_TYPE] = TRUE;
+        }
+      }
+    }
+
+    // Properties.
+    $result = $this->database->select('schemadotorg_properties', 't')
+      ->fields('t', ['id', 'superseded_by', 'sub_property_of', 'range_includes'])
+      ->orderBy('id')
+      ->execute();
+    while ($record = $result->fetchAssoc()) {
+      $id = str_replace('https://schema.org/', '', $record['id']);
+
+      $info[static::SCHEMA_PROPERTIES][$id] = [];
+      if (!empty($record['superseded_by'])) {
+        $info[static::SCHEMA_PROPERTIES][$id][static::SCHEMA_SUPERSEDED] = TRUE;
+      }
+      if (!empty($record['sub_property_of'])) {
+        $info[static::SCHEMA_PROPERTIES][$id]['sub_property_of'] = str_replace('https://schema.org/', '', $record['sub_property_of']);
+      }
+
+      $default_types = $this->parseIds($record['range_includes']);
+      $info[static::SCHEMA_PROPERTIES][$id]['default_type'] = NULL;
+      $sub_types_of_thing = [];
+      foreach ($default_types as $default_type) {
+        // If there is a data type, then we return no default type.
+        if (isset($info[self::SCHEMA_TYPES][$default_type][static::SCHEMA_DATA_TYPE])) {
+          $default_types = [];
+          $sub_types_of_thing = [];
+          break;
+        }
+        // If the default type is a subtype of a schema.org thing use that first.
+        elseif ($types[$default_type]['sub_type_of'] === 'https://schema.org/Thing') {
+          $sub_types_of_thing[$default_type] = $default_types;
+          unset($default_types[$default_type]);
+        }
+        // If the full type is not a thing, remove it.
+        elseif (!isset($info[self::SCHEMA_TYPES][$default_type][static::SCHEMA_THING])) {
+          unset($default_types[$default_type]);
+        }
+      }
+
+      $info[static::SCHEMA_PROPERTIES][$id]['default_type'] = ($sub_types_of_thing || $default_types)
+        ? array_key_first($sub_types_of_thing + $default_types)
+        : NULL;
+
+    }
+
+    $this->cacheBackend->set('schemadotorg_info', $info);
+
+    return $info;
+  }
+
   /**
    * {@inheritdoc}
    */
   public function isId(string $table, string $id): bool {
-    $label = $this->database->select('schemadotorg_' . $table, 't')
-      ->fields('t', ['label'])
-      ->condition('label', $id)
-      ->execute()
-      ->fetchField();
-    // Making sure the 'label' (aka type or property id) is exact match because
-    // SQL queries are case-insensitive.
-    return ($label === $id);
+    $info = $this->getInfo();
+    return isset($info[$table][$id]);
   }
 
   /**
    * {@inheritdoc}
    */
   public function isItem(string $id): bool {
-    return $this->isType($id) || $this->isProperty($id);
+    $info = $this->getInfo();
+    return isset($info[static::SCHEMA_TYPES][$id])
+      || isset($info[static::SCHEMA_PROPERTIES][$id]);
   }
 
   /**
    * {@inheritdoc}
    */
   public function isType(string $id): bool {
-    return $this->isId(static::SCHEMA_TYPES, $id);
+    $info = $this->getInfo();
+    return isset($info[static::SCHEMA_TYPES][$id]);
   }
 
   /**
@@ -107,68 +215,48 @@ class SchemaDotOrgSchemaTypeManager implements SchemaDotOrgSchemaTypeManagerInte
    * {@inheritdoc}
    */
   public function isThing(string $id): bool {
-    $type_definition = $this->getType($id);
-    return (!empty($type_definition)
-      && $type_definition['label'] === $id
-      && !empty($type_definition['properties'])
-      && !in_array($id, ['Enumeration', 'Intangible'])
-    );
+    $info = $this->getInfo();
+    return isset($info[static::SCHEMA_TYPES][$id][static::SCHEMA_THING]);
   }
 
   /**
    * {@inheritdoc}
    */
   public function isDataType(string $id): bool {
-    $data_types = $this->getDataTypes();
-    return (isset($data_types[$id]));
+    $info = $this->getInfo();
+    return isset($info[static::SCHEMA_TYPES][$id][static::SCHEMA_DATA_TYPE]);
   }
 
   /**
    * {@inheritdoc}
    */
   public function isIntangible(string $id): bool {
-    if (!$this->isType($id)) {
-      return FALSE;
-    }
-    elseif ($id === 'Intangible') {
-      return TRUE;
-    }
-    else {
-      $breadcrumbs = $this->getTypeBreadcrumbs($id);
-      foreach ($breadcrumbs as $breadcrumb => $items) {
-        if (str_contains($breadcrumb, '/Intangible/')) {
-          return TRUE;
-        }
-      }
-      return FALSE;
-    }
+    $info = $this->getInfo();
+    return isset($info[static::SCHEMA_TYPES][$id][static::SCHEMA_INTANGIBLE]);
   }
 
   /**
    * {@inheritdoc}
    */
   public function isEnumerationType(string $id): bool {
-    return (boolean) $this->database->select('schemadotorg_types', 'types')
-      ->fields('types', ['id'])
-      ->condition('enumerationtype', $this->getUri($id))
-      ->countQuery()
-      ->execute()
-      ->fetchField();
+    $info = $this->getInfo();
+    return isset($info[static::SCHEMA_TYPES][$id][static::SCHEMA_ENUMERATION_TYPE]);
   }
 
   /**
    * {@inheritdoc}
    */
   public function isEnumerationValue(string $id): bool {
-    $item = $this->getItem(static::SCHEMA_TYPES, $id);
-    return (!empty($item['enumerationtype']));
+    $info = $this->getInfo();
+    return isset($info[static::SCHEMA_TYPES][$id][static::SCHEMA_ENUMERATION_VALUE]);
   }
 
   /**
    * {@inheritdoc}
    */
   public function isProperty(string $id): bool {
-    return $this->isId(static::SCHEMA_PROPERTIES, $id);
+    $info = $this->getInfo();
+    return isset($info[static::SCHEMA_PROPERTIES][$id]);
   }
 
   /**
@@ -183,18 +271,9 @@ class SchemaDotOrgSchemaTypeManager implements SchemaDotOrgSchemaTypeManagerInte
    * {@inheritdoc}
    */
   public function isSuperseded(string $id): bool {
-    if (!isset($this->supersededCache)) {
-      $this->supersededCache = [];
-      foreach ([static::SCHEMA_TYPES, static::SCHEMA_PROPERTIES] as $table) {
-        $ids = $this->database->select('schemadotorg_' . $table, $table)
-          ->fields($table, ['label'])
-          ->condition('superseded_by', '', '<>')
-          ->execute()
-          ->fetchCol();
-        $this->supersededCache += array_combine($ids, $ids);
-      }
-    }
-    return !empty($this->supersededCache[$id]);
+    $info = $this->getInfo();
+    return isset($info[static::SCHEMA_TYPES][$id][static::SCHEMA_SUPERSEDED])
+      || isset($info[static::SCHEMA_PROPERTIES][$id][static::SCHEMA_SUPERSEDED]);
   }
 
   /**
@@ -274,40 +353,8 @@ class SchemaDotOrgSchemaTypeManager implements SchemaDotOrgSchemaTypeManagerInte
    *   The Schema.org property's default Schema.org type from range_includes.
    */
   public function getPropertyDefaultType(string $property): ?string {
-    $property_definition = $this->getProperty($property);
-    if (!$property_definition) {
-      return NULL;
-    }
-
-    $range_includes = $this->parseIds($property_definition['range_includes']);
-    $type_definitions = $this->getTypes($range_includes);
-
-    $sub_types_of_thing = [];
-    foreach ($type_definitions as $type => $type_definition) {
-      // Remove all types definitions without properties
-      // (i.e. Enumerations and Data types).
-      if (empty($type_definition['properties'])) {
-        // If the property range can be a simple data type, do not return a
-        // default type.
-        if ($this->isDataType($type)) {
-          return NULL;
-        }
-        // Otherwise. unset the enumeration.
-        else {
-          unset($type_definitions[$type]);
-        }
-      }
-      // Track subtypes of Thing.
-      elseif ($type_definition['sub_type_of'] === 'https://schema.org/Thing') {
-        $sub_types_of_thing[$type] = $type;
-      }
-    }
-
-    // Make sure subtypes of Thing comes first.
-    $type_definitions = $sub_types_of_thing + $type_definitions;
-
-    // Finally, return the first type in range_includes type definitions.
-    return array_key_first($type_definitions);
+    $info = $this->getInfo();
+    return $info[static::SCHEMA_PROPERTIES][$property]['default_type'];
   }
 
   /**
diff --git a/src/SchemaDotOrgSchemaTypeManagerInterface.php b/src/SchemaDotOrgSchemaTypeManagerInterface.php
index 80d3f40035648698e8e466b090eef33f817e2f68..ab539db52b1cacaf1039a963265a33ff6a286137 100644
--- a/src/SchemaDotOrgSchemaTypeManagerInterface.php
+++ b/src/SchemaDotOrgSchemaTypeManagerInterface.php
@@ -12,15 +12,65 @@ use Drupal\Core\StringTranslation\TranslatableMarkup;
 interface SchemaDotOrgSchemaTypeManagerInterface {
 
   /**
-   * Schema.org type.
+   * Schema.org types.
    */
   const SCHEMA_TYPES = 'types';
 
   /**
-   * Schema.org property.
+   * Schema.org type.
+   */
+  const SCHEMA_TYPE = 'type';
+
+  /**
+   * Schema.org properties.
    */
   const SCHEMA_PROPERTIES = 'properties';
 
+  /**
+   * Schema.org property.
+   */
+  const SCHEMA_PROPERTY = 'property';
+
+  /**
+   * Schema.org thing.
+   */
+  const SCHEMA_THING = 'thing';
+
+  /**
+   * Schema.org intangible.
+   */
+  const SCHEMA_INTANGIBLE = 'intangible';
+
+  /**
+   * Schema.org data type.
+   */
+  const SCHEMA_DATA_TYPE = 'data_type';
+
+  /**
+   * Schema.org enumeration.
+   */
+  const SCHEMA_ENUMERATION = 'enumeration';
+
+  /**
+   * Schema.org enumeration type.
+   */
+  const SCHEMA_ENUMERATION_TYPE = 'enumeration_type';
+
+  /**
+   * Schema.org enumeration value.
+   */
+  const SCHEMA_ENUMERATION_VALUE = 'enumeration_value';
+
+  /**
+   * Schema.org superseded.
+   */
+  const SCHEMA_SUPERSEDED = 'superseded';
+
+  /**
+   * Schema.org default type.
+   */
+  const SCHEMA_DEFAULT_TYPE = 'default_type';
+
   /**
    * The Schema.org base URI.
    */