Doctrine缓存需区分元数据、查询、结果三类并按需配置:元数据缓存实体结构,查询缓存DQL编译结果,结果缓存数据库数据行;生产必启,开发默认关。

Doctrine缓存不是“开个开关”就完事,关键在分清三种缓存类型(元数据、查询、结果)并按需配置后端。生产环境必须启用,开发环境默认关闭——这是性能与调试的平衡点。
三类缓存各司其职
Doctrine ORM 的缓存体系分三层,缺一不可:
- 元数据缓存:缓存实体结构定义(比如字段名、映射关系),避免每次启动都解析注解或YAML。适合用 APCu 或 Redis。
- 查询缓存:缓存 DQL → SQL 的编译结果(即“查询计划”),不存数据本身。对固定 DQL 查询提速明显,但动态参数多时收益有限。
- 结果缓存:真正缓存数据库返回的数据行,命中后完全跳过 SQL 执行。适用于读多写少、时效性要求不高的场景(如分类列表、地区字典)。
YAML 配置(推荐 Symfony 6+)
在 config/packages/doctrine.yaml 中统一声明,生产环境生效:
when@prod:
doctrine:
orm:
auto_generate_proxy_classes: false
metadata_cache_driver:
type: pool
pool: doctrine.system_cache_pool
query_cache_driver:
type: pool
pool: doctrine.system_cache_pool
result_cache_driver:
type: pool
pool: doctrine.result_cache_pool
framework:
cache:
pools:
doctrine.system_cache_pool:
adapter: cache.adapter.redis_tag_aware
default_lifetime: 3600
doctrine.result_cache_pool:
adapter: cache.adapter.redis_tag_aware
default_lifetime: 1800
注意:cache.adapter.redis_tag_aware 支持标签失效,比普通 Redis 适配器更适合 Doctrine 结果缓存;若没 Redis,可用 cache.adapter.php_files 临时过渡,但别用于高并发场景。
代码层启用结果缓存
配置只是基础,具体查询是否缓存,由代码决定:
- Repository 内使用 QueryBuilder 时调用
useResultCache(true, 300, 'my_custom_key'); - 原生 Query 对象可链式调用
->useResultCache(true, 600); - 实体关联加载(如
fetch="EAGER")不会自动走结果缓存,需手动在关联查询中显式启用。
缓存键(key)若不指定,Doctrine 自动生成,但建议自定义带业务语义的 key(如 products_by_category_{$catId}),便于调试和主动清除。
验证与清理
缓存是否真起作用?两个简单方法:
- 查日志:开启
doctrine.dbal.logging: true,观察重复请求是否跳过 SQL 打印; - 看缓存目录:运行
php bin/console cache:clear --env=prod后访问接口,再检查var/cache/prod/pools/doctrine.result_cache_pool/下是否有生成文件(Redis 则需用redis-cli KEYS "*doctrine*"查)。
手动清理某条缓存?用 Doctrine 自带命令:php bin/console doctrine:cache:clear-result --env=prod,或通过服务注入 CacheInterface 调用 deleteItem('my_custom_key')。


















