Redis 查询引擎性能最佳实践
注意
如果您正在使用 Redis Software 或 Redis Cloud,请参阅可扩展 Redis 查询引擎的最佳实践页面。检查清单
以下是一些确保 Redis 查询引擎 (RQE) 良好性能的基本步骤。
- 在设计 Redis 数据模型时考虑您的查询模式。
- 使用大小计算器确保 Redis 架构已根据预期负载调整大小。
- 为 Redis 节点配置足够的资源(RAM、CPU、网络)以支持预期的最大负载。
- 检查
FT.INFO
和FT.PROFILE
的输出,查找异常和/或错误。 - 在测试环境中,使用真实世界的查询和由 memtier_benchmark 或自定义负载应用生成的负载进行负载测试。
索引注意事项
一般
非线程化搜索
线程化(查询性能因子或 QPF)搜索
- 将查询字段和任何投影字段(
RETURN
或LOAD
)都放入索引。 - 将所有字段设置为
SORTABLE
。 - 将 TAG 字段设置为 UNF。
- 可选:如果使用案例支持,将
TEXT
字段设置为NOSTEM
。 - 使用
DIALECT 2
。
查询优化
- 避免返回大型结果集。使用
CURSOR
或LIMIT
。 - 避免通配符搜索。
- 避免投影所有字段(例如,
LOAD *
)。只投影属于索引 schema 的字段。 - 如果查询运行时间长,启用线程化(查询性能因子)以减少对主 Redis 线程的竞争。
验证性能(FT.PROFILE
)
您可以分析 FT.PROFILE
输出,以了解查询执行的详细信息。以下信息项可用于分析:
- 总执行时间
- 每个分片的执行时间
- 协调时间(适用于多分片环境)
- 查询分解为基本组件,例如
UNION
和INTERSECT
- 警告,例如
TIMEOUT
反模式
在设计和查询 RQE 中的索引时,某些做法可能会阻碍性能、可扩展性和可维护性。以下是一些常见的反模式,应予以避免:
- 大型文档:在 Redis 中存储过大的文档会减慢数据检索速度并增加内存使用。尽可能将数据分解为更小、更集中的记录。
- 深层嵌套字段:检索或索引深层嵌套的 JSON 字段计算成本很高。使用更扁平的 schema 以获得更好的性能。
- 大型结果集:获取不必要的大型结果集会占用内存和网络资源。将结果限制在所需范围内。
- 通配符使用:在查询中不加区分地使用通配符模式可能导致大规模且低效的扫描,尤其是在索引规模较大时。
- 大型投影:在查询结果中包含过多字段会增加内存开销并减慢查询执行速度。将投影限制在必需的字段。
以下示例描述了一个反模式索引 schema 和查询,随后是为 RQE 可扩展性设计的更正版本。
反模式索引 schema
以下 schema 带来了可扩展性和性能方面的挑战:
FT.CREATE jsonidx:profiles ON JSON PREFIX 1 profiles:
SCHEMA $.tags.* as t NUMERIC SORTABLE
$.firstName as name TEXT
$.location as loc GEO
问题
- 最小化 schema 定义:该 schema 稀疏,缺少可能频繁查询的字段,如
lastName
、id
和version
。这导致需要额外的操作来单独获取这些字段,降低了效率。 - 文本字段缺少
SORTABLE
标志:对不可排序字段执行排序操作需要全文处理,速度很慢。 - 通配符索引:
$.tags.*
创建了一个广泛的索引,可能导致过度的内存使用和降低的查询性能。
反模式查询
以下查询效率低下,未针对垂直扩展进行优化:
FT.AGGREGATE jsonidx:profiles '@t:[1299 1299]' LOAD * LIMIT 0 10
问题
- 通配符投影(
LOAD *
):在结果集中检索所有字段效率低下,会增加内存使用,尤其是在文档较大的情况下。 - 不必要的字段:当前操作不需要的字段仍然被获取,减慢了执行速度。
- 缺乏高级查询语法:未指定查询方言或利用标签等功能,查询可能执行不必要的计算。
改进的索引 schema
以下是遵循垂直扩展最佳实践的优化 schema:
FT.CREATE jsonidx:profiles ON JSON PREFIX 1 profiles:
SCHEMA $.tags.* as t NUMERIC SORTABLE
$.firstName as name TEXT NOSTEM SORTABLE
$.lastName as lastname TEXT NOSTEM SORTABLE
$.location as loc GEO SORTABLE
$.id as id TAG SORTABLE UNF
$.ver as ver TAG SORTABLE UNF
改进
- 文本字段的
NOSTEM
:防止对firstName
和lastName
等字段进行词干提取,以允许精确匹配(例如,“Smith” 保持 “Smith”)。 - 扩展 schema:添加了常用查询字段,如
lastName
、id
和version
,通过减少查询后数据检索的需要,使查询更高效。 TAG
字段:id
和ver
定义为TAG
字段,以支持快速精确匹配过滤。- 所有相关字段的
SORTABLE
:确保排序操作高效,无需全文扫描。
您可能想知道为什么在改进的 schema 中 $.tags.* as t NUMERIC SORTABLE
是可接受的,而之前不是。包含 $.tags.*
在以下情况下是可以接受的:
- 它有明确的目的:它在查询中被积极使用,例如按数值范围过滤或匹配特定值。
- schema 中的其他字段对其进行补充:这些字段减少了所有查询操作对
$.tags.*
的过度依赖,更均匀地分配负载。 - 投影和限制得到精心管理:使用
$.tags.*
的查询应避免加载不必要的字段或返回过大的结果集。
改进的查询
以下查询更适合垂直扩展:
FT.AGGREGATE jsonidx:profiles '@t:[1299 1299]'
LOAD 6 id t name lastname loc ver
LIMIT 0 10
DIALECT 2
改进
- 定向投影:
LOAD
子句仅指定必需字段(id
,t
,name
,lastname
,loc
,ver
),减少内存和网络开销。 - 限制结果:
LIMIT
子句确保查询仅检索前 10 个结果,避免大型结果集。 DIALECT 2
:启用最新的 RQE 语法和功能,确保与现代功能兼容。