Loading a full node entity when you only need its title is like ordering the entire menu to eat one appetizer — Drupal's Entity API defaults to fully hydrating every field, every translation, every revision reference, even when your code only ever reads $node->getTitle(). On a page rendering hundreds of entities (a large View, a batch operation), that overhead adds up fast.
What you'll learn in this lesson
- Why
loadMultiple()is dramatically cheaper than a loop of individualload()calls - How to fetch only specific field values without loading full entities
- What the static entity cache does for you automatically, and its limits
loadMultiple() instead of a load loop
// Slow: N separate queries.
foreach ($nids as $nid) {
$node = \Drupal::entityTypeManager()->getStorage('node')->load($nid);
}
// Fast: one query for all of them.
$nodes = \Drupal::entityTypeManager()->getStorage('node')->loadMultiple($nids);
Every individual load() call triggers its own database round trip (unless the entity is already statically cached). loadMultiple() batches every ID into a single query, exactly the same "one connection, one query" principle you saw in the Database API topic's dynamic-query lessons.
Fetching only a field value, not the whole entity
$titles = \Drupal::entityTypeManager()
->getStorage('node')
->getQuery()
->condition('type', 'article')
->accessCheck(TRUE)
->execute();
// Still needs loadMultiple() to actually read field values — entityQuery()
// only ever returns IDs. For genuinely field-only reads at scale, query the
// field table directly with Connection::select(), the same DBTNG pattern
// from the Database API topic.
getQuery() never loads entities — it only returns matching IDs, always. Reaching for a raw Connection::select() against the field's own database table (e.g. node__field_example) is the real way to read one field's value across many entities without hydrating full objects, at the cost of losing the Entity API's access checks and field-type abstraction.Quick check: you need just the titles of 500 published articles for a dropdown. Is
loadMultiple()on all 500 nodes the fastest option? If you said no — a directConnection::select()againstnode_field_datafor just thetitlecolumn would be faster, since it skips hydrating every other field — you've got the core trade-off this lesson is about.
Key takeaways
- Always batch entity loads with
loadMultiple()instead of looping individualload()calls. getQuery()/entity queries return IDs only — never field values directly.- For read-only access to a handful of field values across many entities, a raw DBTNG query against the field table beats full entity hydration.
- Drupal's static entity cache means a second
load()of the same ID in one request is free — the expensive part is the first load and cross-request repetition.
Coming up next
Loading entities efficiently is half the story — the other half is making sure the rendered result gets cached correctly so you don't pay that cost again on the next request. Next, entity-based cache tags.