本文属于机器翻译版本。若本译文内容与英语原文存在差异,则一律以英文原文为准。
OpenCypher 遵循一种范式,即数字数据类型(例如 int、byte、short、long 等)的匹配是在类型提升语义下进行的。例如,在类型提升语义下,在查找所有输入值为 10 且为短类型的属性时,它还会匹配长整值为 10 的属性。在某些情况下,类型转换可能会导致开销,并导致查询计划的效率低于未执行类型转换时的效率。尤其是在数据中一致使用数据类型的情况下(例如,如果所有人的年龄都存储为长值),则在不影响查询结果的情况下进行类型提升会产生开销。
为了在已知存储在数据库中的数值属性数据值的类型一致的情况下进行优化,可以使用名为assumeConsistentDataTypes
(带值true/false
,默认值为false
)的查询提示。当此查询提示的值为时true
,引擎会假设唯一的属性值始终为 long 或 double,并将跳过类型提升语义。在查询中指定的数值被视为长值(对于非浮点值)和双精度值(对于浮点值)。
如果数据始终使用单一数据类型(例如,所有年龄段都存储为long
),则使用assumeConsistentDataTypes
提示可以跳过对不同数字类型的不必要的相等性检查,从而优化查询。但是,如果同一属性的数据类型不一致,则使用提示可能会导致某些结果丢失,因为查询只会匹配提示假设的单个数据类型。
# Database loaded with following openCypher CSV's # File 1 :ID,age:Int n1,20 n2,25 # File 2 :ID,age:Long n3,25 # Example (no hint) MATCH (n:Person) WHERE n.age >= 25 RETURN n # Result n2 n3 Returns all person whose age is >= 25 and the values >= 25 can be with any of these datatypes i.e. byte, short, int, long, double or float ----------------------------------------------------------------------------------- # Example (with hint present) USING QUERY:assumeConsistentDataTypes "true" MATCH (n:Person) WHERE n.age >= 25 RETURN n # Result n3 Returns only "n3" and not "n2". The reason is that even though the numerical value matches (25), the datatype is "int" and is considered a non-match.
也可以通过解释来验证差异。
不加解释:
# Query MATCH (n) WHERE n.age = 20 RETURN n # Explain Snippet ╔═════╤══════════╤══════════╤══════════════════════════════╤═══════════════════════════════════════════════════════════════════════════════════════════════════════════════════════════════════════════════════════════════════════╤════════╤════════════╤══════════════╤═════════╤══════════════╗ ║ ID │ Out #1 │ Out #2 │ Name │ Arguments │ Mode │ Units In │ Units Out │ Ratio │ Time (ms) ║ ╠═════╪══════════╪══════════╪══════════════════════════════╪═══════════════════════════════════════════════════════════════════════════════════════════════════════════════════════════════════════════════════════════════════════╪════════╪════════════╪══════════════╪═════════╪══════════════╣ ║ 0 │ 1 │ - │ DFEPipelineScan (DFX) │ pattern=Node(?n) with property 'age' as ?n_age2 and label 'ALL' │ - │ 0 │ 1 │ 0.00 │ 0.10 ║ ║ │ │ │ │ inlineFilters=[(?n_age2 IN ["20"^^xsd:byte, "20"^^xsd:int, "20"^^xsd:long, "20"^^xsd:short, "20.0"^^xsd:double, "20.0"^^xsd:float])] │ │ │ │ │ ║ ║ │ │ │ │ patternEstimate=1 │ │ │ │ │ ║ ╟─────┼──────────┼──────────┼──────────────────────────────┼───────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────┼────────┼────────────┼──────────────┼─────────┼──────────────╢ # The inFilters field contains all numeric types
有提示:
# Query MATCH (n) WHERE n.age = 20 RETURN n # Explain Snippet ╔═════╤══════════╤══════════╤══════════════════════════════╤═════════════════════════════════════════════════════════════════════════════════╤════════╤════════════╤══════════════╤═════════╤══════════════╗ ║ ID │ Out #1 │ Out #2 │ Name │ Arguments │ Mode │ Units In │ Units Out │ Ratio │ Time (ms) ║ ╠═════╪══════════╪══════════╪══════════════════════════════╪═════════════════════════════════════════════════════════════════════════════════╪════════╪════════════╪══════════════╪═════════╪══════════════╣ ║ 0 │ 1 │ - │ DFEPipelineScan (DFX) │ pattern=Node(?n) with property 'age' as ?n_age2 and label 'ALL' │ - │ 0 │ 1 │ 0.00 │ 0.07 ║ ║ │ │ │ │ inlineFilters=[(?n_age2 IN ["20"^^xsd:long])] │ │ │ │ │ ║ ║ │ │ │ │ patternEstimate=1 │ │ │ │ │ ║ ╟─────┼──────────┼──────────┼──────────────────────────────┼─────────────────────────────────────────────────────────────────────────────────┼────────┼────────────┼──────────────┼─────────┼──────────────╢ # The inFilters field only contains long datatype