人大金仓分析型数据库JSON索引

GIN索引

可以使用GIN索引有效地搜索出现在大量jsonb文档(基准)中的键或键/值对。两个GIN操作符类,提供不同的性能和灵活性权衡。jsonb的默认GIN操作符类支持带@>, ?, ?& ?|操作符的查询。使用此操作符类创建索引的示例如下:

CREATE INDEX idxgin ON api USING gin (jdoc);
        非默认的GIN运算符类jsonb_path_ops 仅支持为 @>运算符编制索引。使用此运算符类创建索引的示例如下:
CREATE INDEX idxginp ON api USING gin (jdoc jsonb_path_ops);
         考虑一个表的示例,该表存储从第三方Web服务检索到的JSON文档,并且具有文档化的模式定义。这是一个典型的文档:  
{
"guid": "9c36adc1-7fb5-4d5b-83b4-90356a46061a",
"name": "Angela Barton",
"is_active": true,
"company": "Magnafone",
"address": "178 Howard Place, Gulf, Washington, 702",
"registered": "2009-11-07T08:53:22 +08:00",
"latitude": 19.793713,
"longitude": 86.513373,
"tags": [
"enim",
"aliquip",
"qui"
]
}

        JSON文档存储在jsonb列中的一个名为API的表中。如果在此列上创建了GIN索引,则以下查询可以使用该索引:

-- 查找关键词“公司”具有“magnafone”价值的文档:
SELECT jdoc->'guid', jdoc->'name' FROM api WHERE jdoc @> '{"company": "Magnafone"}';

        但是,索引不能用于以下查询。操作符? 是可索引的,但是,比较不会直接应用于索引列jdoc:

-- Find documents in which the key "tags" contains key or array element "qui"
SELECT jdoc->'guid', jdoc->'name' FROM api WHERE jdoc -> 'tags' ? 'qui';

        通过适当地使用表达式索引,上述查询可以使用索引。如果在tags 键中查询特定项是常见的,那么定义这样的索引可能是值得的:

CREATE INDEX idxgintags ON api USING gin ((jdoc -> 'tags'));
        查询JSON 文档的另一种方法是利用包含性,例如:
-- 查找键“tags”包含数组元素"qui"的文档
SELECT jdoc->'guid', jdoc->'name' FROM api WHERE jdoc @> '{"tags": ["qui"]}';

        jdoc列上的一个简单的GIN索引可以支持这个查询。但是,索引将在jdoc列中存储每个键和值的副本,而前一个示例的表达式索引只存储标记键下的数据。虽然简单索引方法要灵活得多(因为它支持关于任何键的查询),但是目标表达式索引可能比简单索引更小,搜索速度更快。尽管 jsonb_path_ops类只支持带@> 运算符的查询,但它比默认的jsonb_operator类具有性能优势。对于相同的数据, jsonb_path_ops索引通常比jsonb_ops索引小得多,搜索的特殊性更好,尤其是当查询包含频繁出现在数据中的键时。因此,搜索操作通常比默认的operator类执行得更好。jsonb_ops jsonb-path-ops-gin 索引的技术区别在于前者为数据中的每个键和值创建独立的索引项,而后者仅为数据中的每个值创建索引项。

        基本上,每个jsonb_path_ops索引项都是值的散列和指向该值的键;例如,要索引{"foo": {"bar": "baz"}},将创建一个索引项,将foo, bar, baz 中的三个都合并到散列值中。因此,查找此结构的包含查询将导致极其具体的索引搜索;但根本无法确定foo是否显示为键。另一方面,jsonb_ops 索引将分别创建三个表示foo, bar, baz 的索引项;然后,为了执行包含性查询,它将查找包含这三个项的行。虽然GIN索引可以相当有效地执行这样的搜索,但是它仍然比同等的jsonb_path_ops搜索更不具体和更慢,特别是如果有大量的行包含三个索引项中的任何一个。jsonb_path_ops方法的一个缺点是它不会为不包含任何值的json结构生成索引项,例如{"a":{}}:。如果请求搜索包含此类结构的文档,则需要进行完全索引扫描,这非常慢。jsonb_path_ops不适合经常执行这种搜索的应用程序。

哈希索引

      jsonb还支持btreehash索引。只有在检查完整JSON文档的相等性很重要时,这些方法才有用。为完整起见,josonb 基准的btree 排序是:

Object > Array > Boolean > Number > String > Null
Object with n pairs > object with n - 1 pairs
Array with n elements > array with n - 1 elements

        相等键值数的对象按以下顺序进行比较:

key-1, value-1, key-2 ...

        对象键按存储顺序进行比较。特别是,由于较短的键存储在较长的键之前,这可能导致顺序不直观,例如:

{ "aa": 1, "c": 1} > {"b": 1, "d": 1}

        同样,元素数目相等的数组按以下顺序进行比较:

element-1, element-2 ...

        使用与底层数据库数据类型相同的比较规则来比较原始JSON值。使用默认数据库排序规则比较字符串。

你可能感兴趣的:(数据库)