Apache Druid的JSON查詢使用手冊

JSON查詢

概述

JSON查詢是Druid內(nèi)置的本機(jī)查詢,本機(jī)查詢級別較低,與內(nèi)部計算的執(zhí)行方式密切相關(guān)螺垢。json查詢被設(shè)計為輕量級且非常快速地完成赖歌。這意味著,對于更復(fù)雜的分析或構(gòu)建更復(fù)雜的可視化,需要json查詢枉圃。

一、時間序列查詢(Timeseries)

這些類型的查詢采用時間序列查詢對象庐冯,并返回JSON對象數(shù)組孽亲,其中每個對象代表時間序列查詢所要求的值。

時間序列查詢對象示例如下所示:

{
"queryType": "timeseries",
"dataSource": "sample_datasource",
"granularity": "day",
"descending": "true",
"filter": {
    "type": "and",
    "fields": [
    { "type": "selector", "dimension": "sample_dimension1", "value": "sample_value1" },
    { "type": "or",
        "fields": [
        { "type": "selector", "dimension": "sample_dimension2", "value": "sample_value2" },
        { "type": "selector", "dimension": "sample_dimension3", "value": "sample_value3" }
        ]
    }
    ]
},
"aggregations": [
    { "type": "longSum", "name": "sample_name1", "fieldName": "sample_fieldName1" },
    { "type": "doubleSum", "name": "sample_name2", "fieldName": "sample_fieldName2" }
],
"postAggregations": [
    { "type": "arithmetic",
    "name": "sample_divide",
    "fn": "/",
    "fields": [
        { "type": "fieldAccess", "name": "postAgg__sample_name1", "fieldName": "sample_name1" },
        { "type": "fieldAccess", "name": "postAgg__sample_name2", "fieldName": "sample_name2" }
    ]
    }
],
"intervals": [ "2012-01-01T00:00:00.000/2012-01-03T00:00:00.000" ]
}
屬性 描述 必須
queryType 設(shè)置查詢類型為時間序列 timeseries
dataSource 數(shù)據(jù)源
descending 是否進(jìn)行降序排序展父。默認(rèn)值為false(升序)返劲。
intervals 定義查詢時間范圍。
granularity 定義查詢結(jié)果的粒度
filter 過濾器
aggregations 聚合
postAggregations 后聚合
limit 限制結(jié)果數(shù)量栖茉。默認(rèn)值為無限制篮绿。
context 上下文,可用于修改查詢行為吕漂,包括總計和零填充

上面的查詢將從“ sample_datasource”表中返回2個數(shù)據(jù)點(diǎn)搔耕,從2012年1月1日到2012年1月3日之間每天返回一個數(shù)據(jù)點(diǎn)。每個數(shù)據(jù)點(diǎn)將是sample_fieldName1的(long)總和痰娱,sample_fieldName2的(double)總和和sample_fieldName1的(double)結(jié)果除以過濾器集的sample_fieldName2

[
{
    "timestamp": "2012-01-01T00:00:00.000Z",
    "result": { "sample_name1": <some_value>, "sample_name2": <some_value>, "sample_divide": <some_value> }
},
{
    "timestamp": "2012-01-02T00:00:00.000Z",
    "result": { "sample_name1": <some_value>, "sample_name2": <some_value>, "sample_divide": <some_value> }
}
]

Druid可以在時間序列結(jié)果集的最后一行包含額外的“總計”行弃榨。要啟用此功能,請?zhí)砑?"grandTotal":true 到您的查詢context中梨睁【ňΓ總計行將在結(jié)果數(shù)組中顯示為最后一行。即使查詢以“降序”模式運(yùn)行坡贺,也將是最后一行官辈。總計行中的后聚合將基于總計匯總進(jìn)行計算遍坟。

{
"queryType": "timeseries",
"dataSource": "sample_datasource",
"intervals": [ "2012-01-01T00:00:00.000/2012-01-03T00:00:00.000" ],
"granularity": "day",
"aggregations": [
    { "type": "longSum", "name": "sample_name1", "fieldName": "sample_fieldName1" },
    { "type": "doubleSum", "name": "sample_name2", "fieldName": "sample_fieldName2" }
],
"context": {
    "grandTotal": true
}
}

時間序列查詢通常用零填充空的結(jié)果段拳亿。如,如果您對間隔2012-01-01/2012-01-04發(fā)送“day”粒度時間序列查詢愿伴,而2012-01-02沒有數(shù)據(jù)肺魁,您將收到:

[
{
    "timestamp": "2012-01-01T00:00:00.000Z",
    "result": { "sample_name1": <some_value> }
},
{
"timestamp": "2012-01-02T00:00:00.000Z",
"result": { "sample_name1": 0 }
},
{
    "timestamp": "2012-01-03T00:00:00.000Z",
    "result": { "sample_name1": <some_value> }
}
]

完全位于數(shù)據(jù)間隔之外的時間段不會填充零。

您可以使用context標(biāo)記"skipEmptyBuckets": "true"跳過空結(jié)果填充隔节。在這種模式下鹅经,結(jié)果中將省略2012-01-02的數(shù)據(jù)點(diǎn)寂呛。

{
"queryType": "timeseries",
"dataSource": "sample_datasource",
"granularity": "day",
"aggregations": [
    { "type": "longSum", "name": "sample_name1", "fieldName": "sample_fieldName1" }
],
"intervals": [ "2012-01-01T00:00:00.000/2012-01-04T00:00:00.000" ],
"context" : {
    "skipEmptyBuckets": "true"
}
}

二、TopN查詢(TopN)

Druid TopN查詢根據(jù)某些條件返回的結(jié)果集中進(jìn)行排序的結(jié)果瘾晃。從理論上講贷痪,可以將它們視為具有Ordering規(guī)范的單個維度上的近似GroupByQuery查詢。在此用例中蹦误,TopN比GroupBy更快劫拢,資源效率更高。這些類型的查詢采用topN查詢對象强胰,并返回JSON對象數(shù)組舱沧,其中每個對象代表topN查詢所要求查詢條件。

TopN是近似值哪廓,因為每個數(shù)據(jù)集處理時狗唉,將對它們的前K個結(jié)果進(jìn)行排名初烘,并且僅將這些前K個結(jié)果返回給Broker涡真。K在數(shù)據(jù)庫中默認(rèn)為 max(1000, threshold)。實際上肾筐,這意味著如果您要求返回前1000個結(jié)果哆料,則前900個結(jié)果的正確性將為100%,后續(xù)的結(jié)果則不能保證100%的正確和有序性吗铐,所以通過更改max的設(shè)置可以使TopN更加準(zhǔn)確东亦。

{
"queryType": "topN",
"dataSource": "sample_data",
"dimension": "sample_dim",
"threshold": 5,
"metric": "count",
"granularity": "all",
"filter": {
    "type": "and",
    "fields": [
    {
        "type": "selector",
        "dimension": "dim1",
        "value": "some_value"
    },
    {
        "type": "selector",
        "dimension": "dim2",
        "value": "some_other_val"
    }
    ]
},
"aggregations": [
    {
    "type": "longSum",
    "name": "count",
    "fieldName": "count"
    },
    {
    "type": "doubleSum",
    "name": "some_metric",
    "fieldName": "some_metric"
    }
],
"postAggregations": [
    {
    "type": "arithmetic",
    "name": "average",
    "fn": "/",
    "fields": [
        {
        "type": "fieldAccess",
        "name": "some_metric",
        "fieldName": "some_metric"
        },
        {
        "type": "fieldAccess",
        "name": "count",
        "fieldName": "count"
        }
    ]
    }
],
"intervals": [
    "2013-08-31T00:00:00.000/2013-09-03T00:00:00.000"
]
}
屬性 描述 必要
queryType 設(shè)置查詢類型為時間序列 topN
dataSource 數(shù)據(jù)源
intervals 定義查詢時間范圍。
granularity 定義查詢結(jié)果的粒度
filter 過濾器
aggregations 聚合
postAggregations 后聚合
dimension 一個String或JSON對象唬渗,定義使用的類型
threshold 定義TopN中N的值
metric 一個String或JSON對象典阵,它指定要排序的指標(biāo)
context 上下文
[
{
    "timestamp": "2013-08-31T00:00:00.000Z",
    "result": [
    {
        "dim1": "dim1_val",
        "count": 111,
        "some_metrics": 10669,
        "average": 96.11711711711712
    },
    {
        "dim1": "another_dim1_val",
        "count": 88,
        "some_metrics": 28344,
        "average": 322.09090909090907
    },
    {
        "dim1": "dim1_val3",
        "count": 70,
        "some_metrics": 871,
        "average": 12.442857142857143
    },
    {
        "dim1": "dim1_val4",
        "count": 62,
        "some_metrics": 815,
        "average": 13.14516129032258
    },
    {
        "dim1": "dim1_val5",
        "count": 60,
        "some_metrics": 2787,
        "average": 46.45
    }
    ]
}
]

多值維度

topN查詢可以對多值維度進(jìn)行分組。在對多值維度進(jìn)行分組時镊逝,匹配行中的所有值將用于為每個值生成一組壮啊。查詢返回的組可能比行多。例如撑蒜,一個TopN的字段 tags 經(jīng)過過濾器 "t1" AND "t3" 將只有ROW1一個匹配歹啼,最終與三個組生成結(jié)果:t1,t2座菠,和t3狸眼。如果只需要包含與過濾器匹配的值,則可以使用過濾的 DimensionSpec屬性設(shè)置可以少返回一些結(jié)果浴滴,這也可以提高性能拓萌。

混疊

  • 當(dāng)前的TopN算法是一種近似算法。返回每個段的前1000個局部結(jié)果合并以確定全局topN升略。這樣司志,topN算法在等級和結(jié)果上都是近似的甜紫。近似結(jié)果僅適用于超過1000個結(jié)果值的情況。少于1000個唯一維度值的維度上的topN可以被認(rèn)為是排名準(zhǔn)確且集合體準(zhǔn)確骂远。

  • 閾值可以通過服務(wù)器參數(shù)默認(rèn)值1000進(jìn)行修改囚霸,該參數(shù) Druid.query.topN.minTopNThreshold 需要重新啟動服務(wù)器才能生效,或者在查詢上下文中設(shè)置(對每個查詢生效)minTopNThreshold激才。

  • 如果您希望TopN的N數(shù)拓型,則均勻分布的維度前100個按一些low-cardinality,均勻分布的維度排序瘸恼,則可能會找回丟失數(shù)據(jù)的聚合劣挫。

  • 換句話說,topN的最佳用例是您可以確信總體結(jié)果始終位于頂部东帅。例如压固,如果某個特定的站點(diǎn)ID在每天的每個小時中均處于某個指標(biāo)的前10名中,則它在幾天之內(nèi)在前N名中可能很準(zhǔn)確靠闭。但是帐我,如果某個站點(diǎn)在任何給定的小時內(nèi)幾乎都沒有進(jìn)入前1000名,但在整個查詢粒度中都排名前500名(例如:一個站點(diǎn)在數(shù)據(jù)集中與具有高度周期性數(shù)據(jù)的站點(diǎn)混合在一起獲得高度統(tǒng)一的流量)愧膀,則top500查詢可能沒有使該特定網(wǎng)站具有確切的排名拦键,并且對于該特定網(wǎng)站的匯總可能并不準(zhǔn)確。

  • 在使用TopN之前檩淋,請考慮是否確實需要確切的結(jié)果芬为。獲得準(zhǔn)確的結(jié)果是非常耗費(fèi)資源的過程。對于絕大多數(shù)結(jié)果集來說蟀悦,近似topN算法可提供足夠的準(zhǔn)確性媚朦。

  • 希望獲得具有大于1000個唯一值的維度上,要求精確排名和精確聚合時日戈,應(yīng)發(fā)出groupBy查詢并自行對結(jié)果進(jìn)行排序询张。

  • 可以容忍具有大于1000個唯一值的維度上,允許近似結(jié)果集時,但需要精確的集合涎拉,用戶可以發(fā)出兩個查詢瑞侮,一個用于獲取近似topN的N個值,另一個用于N個值使用選擇過濾器的topN鼓拧,該過濾器僅使用第一個的topN結(jié)果半火。

  • 示例一:

    {
        "aggregations": [
            {
                "fieldName": "L_QUANTITY_longSum",
                "name": "L_QUANTITY_",
                "type": "longSum"
            }
        ],
        "dataSource": "tpch_year",
        "dimension":"l_orderkey",
        "granularity": "all",
        "intervals": [
            "1900-01-09T00:00:00.000Z/2992-01-10T00:00:00.000Z"
        ],
        "metric": "L_QUANTITY_",
        "queryType": "topN",
        "threshold": 2
    }
    
  • 示例二:

    {
        "aggregations": [
            {
                "fieldName": "L_TAX_doubleSum",
                "name": "L_TAX_",
                "type": "doubleSum"
            },
            {
                "fieldName": "L_DISCOUNT_doubleSum",
                "name": "L_DISCOUNT_",
                "type": "doubleSum"
            },
            {
                "fieldName": "L_EXTENDEDPRICE_doubleSum",
                "name": "L_EXTENDEDPRICE_",
                "type": "doubleSum"
            },
            {
                "fieldName": "L_QUANTITY_longSum",
                "name": "L_QUANTITY_",
                "type": "longSum"
            },
            {
                "name": "count",
                "type": "count"
            }
        ],
        "dataSource": "tpch_year",
        "dimension":"l_orderkey",
        "filter": {
            "fields": [
                {
                    "dimension": "l_orderkey",
                    "type": "selector",
                    "value": "103136"
                },
                {
                    "dimension": "l_orderkey",
                    "type": "selector",
                    "value": "1648672"
                }
            ],
            "type": "or"
        },
        "granularity": "all",
        "intervals": [
            "1900-01-09T00:00:00.000Z/2992-01-10T00:00:00.000Z"
        ],
        "metric": "L_QUANTITY_",
        "queryType": "topN",
        "threshold": 2
    }
    

三、分組查詢(GroupBy)

Druid查詢采用groupBy查詢對象季俩,并返回JSON對象數(shù)組钮糖,其中每個對象代表查詢所要求的分組條件。

注意:如果要使用時間作為唯一分組進(jìn)行聚合,或者在單個維度上使用有序的groupBy進(jìn)行聚合店归,請考慮使用Timeseries和TopN查詢以及groupBy阎抒。在某些情況下,它們的性能可能會更好消痛。

{
"queryType": "groupBy",
"dataSource": "sample_datasource",
"granularity": "day",
"dimensions": ["country", "device"],
"limitSpec": { "type": "default", "limit": 5000, "columns": ["country", "data_transfer"] },
"filter": {
    "type": "and",
    "fields": [
    { "type": "selector", "dimension": "carrier", "value": "AT&T" },
    { "type": "or",
        "fields": [
        { "type": "selector", "dimension": "make", "value": "Apple" },
        { "type": "selector", "dimension": "make", "value": "Samsung" }
        ]
    }
    ]
},
"aggregations": [
    { "type": "longSum", "name": "total_usage", "fieldName": "user_count" },
    { "type": "doubleSum", "name": "data_transfer", "fieldName": "data_transfer" }
],
"postAggregations": [
    { "type": "arithmetic",
    "name": "avg_usage",
    "fn": "/",
    "fields": [
        { "type": "fieldAccess", "fieldName": "data_transfer" },
        { "type": "fieldAccess", "fieldName": "total_usage" }
    ]
    }
],
"intervals": [ "2012-01-01T00:00:00.000/2012-01-03T00:00:00.000" ],
"having": {
    "type": "greaterThan",
    "aggregation": "total_usage",
    "value": 100
}
}
屬性 描述 必要
queryType 設(shè)置查詢類型為時間序列 groupBy
dataSource 數(shù)據(jù)源
dimensions 一個用于進(jìn)行分組的維度的JSON列表
limitSpec 請參limitSpec具體用法
having 請參having具體用法
granularity 定義查詢結(jié)果的粒度
filter 過濾器
aggregations 聚合
postAggregations 后聚合
intervals 定義查詢時間范圍且叁。
subtotalsSpec 一個JSON數(shù)組數(shù)組,用于返回其他結(jié)果集秩伞,以對頂級子集進(jìn)行分組dimensions
context 上下文

上面的查詢將返回n * m個數(shù)據(jù)點(diǎn)逞带,最多可返回5000個點(diǎn),其中n是country維的基數(shù)纱新,m是device維的基數(shù)展氓。device維介于sample_datasource表的2012-01-01到2012-01-03之間的每一天司忱,如果數(shù)據(jù)點(diǎn)的值大于100塑煎,那么每個數(shù)據(jù)點(diǎn)都包含total_usage的(long)和、data_transfer的(double)和,total_usage除以data_transfer針對的特定分組,過濾器集country和device

[
{
    "version" : "v1",
    "timestamp" : "2012-01-01T00:00:00.000Z",
    "event" : {
    "country" : <some_dim_value_one>,
    "device" : <some_dim_value_two>,
    "total_usage" : <some_value_one>,
    "data_transfer" :<some_value_two>,
    "avg_usage" : <some_avg_usage_value>
    }
},
{
    "version" : "v1",
    "timestamp" : "2012-01-01T00:00:12.000Z",
    "event" : {
    "dim1" : <some_other_dim_value_one>,
    "dim2" : <some_other_dim_value_two>,
    "sample_name1" : <some_other_value_one>,
    "sample_name2" :<some_other_value_two>,
    "avg_usage" : <some_other_avg_usage_value>
    }
},
...
]

多值維度

groupBy查詢可以對多值維度進(jìn)行分組呻逆。在對多值維度進(jìn)行分組時簿废,匹配行中的所有值將用于為每個值生成一組空入。查詢返回的組可能比行多。例如捏鱼,在查詢結(jié)果的GROUPBY tags與過濾器"t1" AND "t3"將只ROW1最終匹配执庐,但是與三個組生成結(jié)果:t1酪耕,t2导梆,和t3。如果只需要包含與過濾器匹配的值迂烁,則可以使用過濾的DimensionSpec減少返回的結(jié)果數(shù)量看尼,這也可以提高性能。

小計功能信息

小計功能允許在單個查詢中計算多個子組盟步。若要使用此功能,請在查詢中添加一個“subtotalsSpec”屬性却盘,該列表應(yīng)該是子組維度集的列表狰域。它應(yīng)在“維度”屬性中包含維度中的“outputName”,其順序與在“維度”屬性中出現(xiàn)的順序相同

{
"type": "groupBy",
 ...
 ...
"dimensions": [
  {
  "type" : "default",
  "dimension" : "d1col",
  "outputName": "D1"
  },
  {
  "type" : "extraction",
  "dimension" : "d2col",
  "outputName" :  "D2",
  "extractionFn" : extraction_func
  },
  {
  "type":"lookup",
  "dimension":"d3col",
  "outputName":"D3",
  "name":"my_lookup"
  }
],
...
...
"subtotalsSpec":[ ["D1", "D2", D3"], ["D1", "D3"], ["D3"]],
..

}

返回的結(jié)果等同于將3個groupBy查詢的結(jié)果與 DimensionSpec 的json blob 連接在一起黄橘,其中“dimensions”字段為[“ D1”兆览,“ D2”,D3“]塞关,[” D1“抬探,” D3“]和[” D3“] 就像上面的查詢中使用的一樣。

[
  {
    "version" : "v1",
    "timestamp" : "t1",
    "event" : { "D1": "..", "D2": "..", "D3": ".." }
    }
  },
    {
    "version" : "v1",
    "timestamp" : "t2",
    "event" : { "D1": "..", "D2": "..", "D3": ".." }
    }
  },
  ...
  ...

   {
    "version" : "v1",
    "timestamp" : "t1",
    "event" : { "D1": "..", "D3": ".." }
    }
  },
    {
    "version" : "v1",
    "timestamp" : "t2",
    "event" : { "D1": "..", "D3": ".." }
    }
  },
  ...
  ...

  {
    "version" : "v1",
    "timestamp" : "t1",
    "event" : { "D3": ".." }
    }
  },
    {
    "version" : "v1",
    "timestamp" : "t2",
    "event" : { "D3": ".." }
    }
  },
...
]

[1] 實現(xiàn)細(xì)節(jié)

策略

可以使用兩種不同的策略來執(zhí)行GroupBy查詢帆赢。集群的默認(rèn)策略由Broker上的“ Druid.query.groupBy.defaultStrategy”運(yùn)行時屬性確定小压∠吖#可以在查詢上下文中使用“groupByStrategy”來覆蓋它。如果既未設(shè)置上下文字段也未設(shè)置屬性怠益,則將使用"v2"策略仪搔。

  • 默認(rèn)情況下,"v2"旨在提供更好的性能和內(nèi)存管理蜻牢。該策略的使用僻造,完全是堆外映射生成每個段的結(jié)果。數(shù)據(jù)處理使用的是孩饼,完全堆外并發(fā)實時映射和堆上字符串字典合并成每個段結(jié)果髓削。這可能會涉及磁盤溢出。數(shù)據(jù)進(jìn)程將排序后的結(jié)果返回給borker镀娶,borker使用N路合并來合并結(jié)果流立膛。如有必要,borker將具體化結(jié)果(例如梯码,如果查詢按其維度以外的列進(jìn)行排序)宝泵。否則,它會在合并結(jié)果時將結(jié)果流回轩娶。

  • 傳統(tǒng)策略"v1"使用部分堆(維度鍵和地圖本身)和部分堆(合計值)的映射在數(shù)據(jù)流程(歷史記錄儿奶,實時,MiddleManager)上生成每段結(jié)果鳄抒。然后闯捎,數(shù)據(jù)處理使用Druid的索引機(jī)制合并每個段的結(jié)果。默認(rèn)情況下许溅,此合并是多線程的瓤鼻,但也可以選擇是單線程的。borker再次使用Druid的索引機(jī)制合并最終結(jié)果集贤重。borker合并始終是單線程的茬祷。因為Broker使用索引機(jī)制合并結(jié)果,所以它必須在返回任何結(jié)果之前實現(xiàn)完整的結(jié)果集并蝗。在數(shù)據(jù)進(jìn)程和borker上祭犯,默認(rèn)情況下,合并索引完全處于堆中狀態(tài)滚停,但是可以選擇將聚集值存儲在堆外沃粗。

v1和v2之間的區(qū)別

查詢API和結(jié)果,在兩個策略之間是兼容的;但是铐刘,從集群配置角度來看陪每,存在一些差異:

  • groupBy v1使用基于行的限制(maxResults)控制資源使用,而groupBy v2使用基于字節(jié)的限制。另外檩禾,groupBy v1合并結(jié)果在堆上挂签,而groupBy v2合并結(jié)果在堆外。這些因素意味著內(nèi)存調(diào)整和資源限制在v1和v2之間表現(xiàn)不同盼产。尤其是由于這個原因饵婆,某些可以在一個引擎中成功完成的查詢可能會超出資源限制。

  • groupBy v1對并發(fā)運(yùn)行的查詢數(shù)量沒有限制戏售,而groupBy v2通過使用有限大小的合并緩沖池來控制內(nèi)存使用侨核。默認(rèn)情況下,合并緩沖區(qū)的數(shù)量是處理線程數(shù)量的1/4灌灾。您可以根據(jù)需要進(jìn)行調(diào)整搓译,以平衡并發(fā)和內(nèi)存使用。

  • groupBy v1支持在Broker或Historical進(jìn)程上進(jìn)行緩存锋喜,而groupBy v2僅支持在Historical進(jìn)程上進(jìn)行緩存些己。

  • groupBy v1支持使用chunkPeriod并行化執(zhí)行Broker上的合并,而groupBy v2則忽略chunkPeriod嘿般。

  • groupBy v2支持基于數(shù)組的聚合和基于哈希的聚合段标。僅當(dāng)分組鍵是單個索引字符串列時才使用基于數(shù)組的聚合。在基于數(shù)組的聚合中炉奴,將字典編碼的值用作索引逼庞,因此可以直接訪問數(shù)組中的聚合值,而無需基于哈希查找存儲瞻赶。

[2] 內(nèi)存調(diào)整和資源限制

使用groupBy v2策略時赛糟,三個參數(shù)控制資源的使用和限制:

  • Druid.processing.buffer.sizeBytes:每個查詢用于聚合的堆外哈希表的大小,以字節(jié)為單位共耍。最多的Druid.processing.numMergeBuffers將立即創(chuàng)建其中的一個虑灰,這也作為并發(fā)運(yùn)行的groupBy查詢數(shù)量的上限吨瞎。

  • Druid.query.groupBy.maxMergingDictionarySize:堆查詢時按每個查詢痹兜,對字符串進(jìn)行分組的字典的大小(以字節(jié)為單位)颤诀。請注意字旭,這是基于對字典大小的粗略估算,而不是實際大小崖叫。

  • Druid.query.groupBy.maxOnDiskStorage:磁盤上用于聚合的空間量遗淳,每個查詢,以字節(jié)為單位心傀。默認(rèn)情況下屈暗,該值為0,這意味著聚合將不使用磁盤。

    如果maxOnDiskStorage為0(默認(rèn)值)养叛,則超過堆上字典大小的限制或堆外聚合表的限制种呐,則查詢失敗,并顯示“超出資源限制”錯誤弃甥,描述已超過的限制爽室。

    如果maxOnDiskStorage大于0,則超出內(nèi)存限制的查詢將開始使用磁盤進(jìn)行聚合淆攻。在這種情況下阔墩,當(dāng)堆上字典大小或堆外哈希表被填滿時,將對部分聚合的記錄進(jìn)行排序并將其刷新到磁盤瓶珊。然后啸箫,將清除兩個內(nèi)存結(jié)構(gòu)以進(jìn)行進(jìn)一步聚合。查詢超過maxOnDiskStorage設(shè)置的將失敗伞芹,并顯示“超出資源限制”錯誤筐高,表明它們已用完磁盤空間。

    使用groupBy v2策略丑瞧,集群操作者應(yīng)確保對于最大可能的并發(fā)查詢負(fù)載(由提供Druid.processing.numMergeBuffers)柑土,堆外哈希表和堆上合并字典不會超出可用內(nèi)存 。

    Broker不需要基本groupBy查詢的合并緩沖區(qū)绊汹。query如果只有一個子查詢稽屏,則帶有子查詢的查詢(使用dataSource)需要一個合并緩沖區(qū),如果有一層以上的嵌套子查詢西乖,則需要兩個合并緩沖區(qū)狐榔。具有小計的查詢需要一個合并緩沖區(qū)。它們可以彼此疊加:一個具有多層嵌套子查詢層的groupBy查詢(也使用小計)將需要三個合并緩沖區(qū)获雕。

    Historicals和提取任務(wù)的每個groupBy查詢都需要一個合并緩沖區(qū)薄腻,除非啟用了并行組合,在這種情況下届案,每個查詢都需要兩個合并緩沖區(qū)庵楷。

    使用groupBy v1策略時,所有聚合都在堆上完成楣颠,而資源限制則通過參數(shù)Druid.query.groupBy.maxResults設(shè)置尽纽。這是結(jié)果集中最大結(jié)果數(shù)的上限。超過此限制的查詢將失敗童漩,并顯示“超出資源限制”錯誤弄贿,表明它們超過了行限制。集群操作者應(yīng)確保對于預(yù)期的并發(fā)查詢負(fù)載矫膨,堆上聚合不會超出可用的JVM堆空間差凹。

[3] groupBy v2策略的性能調(diào)優(yōu)

  • 限制疊加優(yōu)化

    Druid limit盡可能將groupBy查詢中的規(guī)范下推到Historicals上進(jìn)行細(xì)分期奔,以盡早刪減不必要的中間結(jié)果,并最大程度地減少傳輸給Brokers的數(shù)據(jù)量危尿。默認(rèn)情況下能庆,僅當(dāng)orderBy規(guī)范中的所有字段都是分組鍵的子集時才應(yīng)用此技術(shù)。這是因為脚线,limitPushDown如果orderBy規(guī)范中包含不在分組鍵中的任何字段搁胆,則不能保證準(zhǔn)確的結(jié)果。如果您接受諸如topN查詢中的快速查詢處理的準(zhǔn)確性時邮绿,也可以啟用此技術(shù)渠旁。

  • 優(yōu)化哈希表

    groupBy v2策略使用開放式地址哈希表進(jìn)行匯總。哈希表使用給定的初始存儲桶編號進(jìn)行初始化船逮,并在緩沖區(qū)已滿時逐漸增長顾腊。在哈希沖突中,使用線性探測技術(shù)挖胃。

    初始存儲桶的默認(rèn)大小為1024杂靶,哈希表的默認(rèn)最大負(fù)載因子為0.7。如果您在哈希表中看到太多沖突酱鸭,則可以調(diào)整這些數(shù)字吗垮。bufferGrouperInitialBuckets和bufferGrouperMaxLoadFactor在高級GROUPBY V2策略配置中有相關(guān)說明。

  • 平行組合

    Historicals使用哈希表完成聚合后凹髓,將對聚合結(jié)果進(jìn)行排序和合并烁登,然后再將其發(fā)送到Broker中以進(jìn)行Broker中的N路合并聚合。默認(rèn)情況下蔚舀,Historicals使用所有可用的處理線程(由配置Druid.processing.numThreads)進(jìn)行聚合饵沧,但使用單個線程對聚合進(jìn)行排序和合并,這是將線程發(fā)送到Broker的http線程赌躺。

    這是為了防止某些繁重的groupBy查詢阻止其他查詢狼牺。在Druid中,處理線程在所有提交的查詢之間共享礼患,并且它們不可中斷是钥。這意味著,如果繁重的查詢占用了所有可用的處理線程讶泰,則所有其他查詢都可能被阻塞咏瑟,直到繁重的查詢完成為止。GroupBy查詢通常比時間序列查詢或topN查詢花費(fèi)更多的時間痪署,因此應(yīng)盡快釋放處理線程。

    但是兄旬,您可能會關(guān)心一些非常繁瑣的groupBy查詢的性能狼犯。通常余寥,繁重的groupBy查詢的性能瓶頸是合并排序的聚合。在這種情況下悯森,您也可以使用處理線程宋舷。這稱為并行合并。要啟用并行合并瓢姻,請參閱numParallelCombineThreads“ 高級groupBy v2策略配置”祝蝠。請注意,只有在實際溢出數(shù)據(jù)時才能啟用并行組合(請參閱內(nèi)存調(diào)整和資源限制)幻碱。

    啟用并行合并后绎狭,groupBy v2策略可以創(chuàng)建合并樹以合并排序的聚合。樹的每個中間節(jié)點(diǎn)都是一個線程褥傍,用于合并子節(jié)點(diǎn)的聚合儡嘶。葉節(jié)點(diǎn)線程從哈希表(包括溢出表)讀取和合并聚合。通常恍风,葉進(jìn)程比中間節(jié)點(diǎn)慢蹦狂,因為它們需要從磁盤讀取數(shù)據(jù)。結(jié)果朋贬,默認(rèn)情況下凯楔,較少的線程用于中間節(jié)點(diǎn)。您可以更改中間節(jié)點(diǎn)的程度锦募。

    請注意啼辣,每個Historicals都需要兩個合并緩沖區(qū)來通過并行合并處理groupBy v2策略查詢:一個用于計算每個段的中間聚合,另一個用于并行合并中間聚合御滩。

[4] 備選方案

在某些情況下鸥拧,其他查詢類型可能比groupBy更好。

對于沒有“維度”的查詢(即僅按時間分組)削解,時間序列查詢通常比groupBy更快富弦。主要區(qū)別在于,它以完全流式方式實現(xiàn)(利用段已按時間排序的事實)氛驮,并且不需要使用哈希表進(jìn)行合并腕柜。

對于具有單個“維度”元素(即按一個字符串維度分組)的查詢,TopN查詢 有時會比groupBy更快矫废。

[5] 內(nèi)置的groupby

對于"v1"和"v2"盏缤,內(nèi)置的groupBys(“查詢”類型的數(shù)據(jù)源)的執(zhí)行方式有所不同。Broker首先以通常的方式運(yùn)行內(nèi)部groupBy查詢蓖扑。然后唉铜,"v1"策略使用Druid的索引機(jī)制,在內(nèi)部,實現(xiàn)內(nèi)部查詢,并在這些實現(xiàn)的結(jié)果上運(yùn)行外部查詢律杠。"v2"策略則使用可溢出到磁盤的堆外實時映射和堆上字符串字典潭流,在內(nèi)部查詢的結(jié)果流上運(yùn)行外部查詢竞惋。兩種策略都以單線程方式在Broker上執(zhí)行外部查詢。

[6] 配置

本節(jié)介紹groupBy查詢的配置灰嫉。您可以runtime.properties在Broker拆宛,Historical和MiddleManager進(jìn)程的文件中設(shè)置運(yùn)行時屬性。您可以通過查詢上下文設(shè)置查詢上下文參數(shù)讼撒。

  • groupBy v2的配置

    運(yùn)行時屬性

    屬性 描述 默認(rèn)
    Druid.query.groupBy.maxMergingDictionarySize 合并期間用于字符串字典的最大堆空間量(大約)浑厚。當(dāng)字典超過此大小時,將觸發(fā)溢出到磁盤根盒。 100000000
    Druid.query.groupBy.maxOnDiskStorage 合并緩沖區(qū)或字典填滿時钳幅,每個查詢用于將結(jié)果集溢出到磁盤的最大磁盤空間量。超過此限制的查詢將失敗郑象。設(shè)置為零可禁用使用磁盤贡这。 0(禁用)

    查詢上下文:

    屬性 描述
    maxMergingDictionarySize 可用于降低Druid.query.groupBy.maxMergingDictionarySize的默認(rèn)值。
    maxOnDiskStorage 可用于降低Druid.query.groupBy.maxOnDiskStorage的默認(rèn)值厂榛。
  • 高級配置(通用配置)

    運(yùn)行時屬性:

    屬性 描述 默認(rèn)
    Druid.query.groupBy.defaultStrategy 默認(rèn)groupBy查詢策略盖矫。 v2
    Druid.query.groupBy.singleThreaded 使用單個線程合并結(jié)果。

    查詢上下文:

    屬性 描述
    groupByStrategy 覆蓋Druid.query.groupBy.defaultStrategy的默認(rèn)值击奶。
    groupByIsSingleThreaded 覆蓋Druid.query.groupBy.singleThreaded的默認(rèn)值辈双。
  • GroupBy v2配置

    運(yùn)行時屬性:

    屬性 描述 默認(rèn)
    Druid.query.groupBy.bufferGrouperInitialBuckets 堆外哈希表中用于結(jié)果分組的初始存儲桶數(shù)。設(shè)置為0以使用合理的默認(rèn)值(1024)柜砾。 0
    Druid.query.groupBy.bufferGrouperMaxLoadFactor 用于結(jié)果分組的堆外哈希表的最大負(fù)載因子湃望。當(dāng)負(fù)載系數(shù)超過此大小時,表將增長或溢出到磁盤痰驱。設(shè)置為0以使用合理的默認(rèn)值(0.7)证芭。 0
    Druid.query.groupBy.forceHashAggregation 強(qiáng)制使用基于哈希的聚合。
    Druid.query.groupBy.intermediateCombineDegree 合并樹中合并在一起的中間節(jié)點(diǎn)數(shù)担映。更高的級別需要更少的線程废士,如果服務(wù)器有足夠強(qiáng)大的cpu核心,那么通過減少太多線程的開銷蝇完,這可能有助于提高查詢性能 8
    Druid.query.groupBy.numParallelCombineThreads 并行合并線程的數(shù)量官硝。該值應(yīng)大于1以啟用并行合并功能。用于并行合并的實際線程數(shù)為min(Druid.query.groupBy.numParallelCombineThreads短蜕,Druid.processing.numThreads)氢架。 1(已禁用)
    Druid.query.groupBy.applyLimitPushDownToSegment 如果Broker將下限限制到可查詢的節(jié)點(diǎn)(Historicals,peons)朋魔,則在段掃描期間限制結(jié)果岖研。 真(啟用)

    查詢上下文:

    屬性 描述 默認(rèn)
    bufferGrouperInitialBuckets 覆蓋Druid.query.groupBy.bufferGrouperInitialBuckets的默認(rèn)值。 沒有
    bufferGrouperMaxLoadFactor 覆蓋Druid.query.groupBy.bufferGrouperMaxLoadFactor的默認(rèn)值铺厨。 沒有
    forceHashAggregation 覆蓋Druid.query.groupBy.forceHashAggregation的默認(rèn)值缎玫。 沒有
    intermediateCombineDegree 覆蓋Druid.query.groupBy.intermediateCombineDegree的默認(rèn)值硬纤。 沒有
    numParallelCombineThreads 覆蓋Druid.query.groupBy.numParallelCombineThreads的默認(rèn)值解滓。 沒有
    sortByDimsFirst 首先按維度值對結(jié)果排序赃磨,然后按時間戳排序。
    forceLimitPushDown 當(dāng)orderby中的所有字段都是分組鍵的一部分時洼裤,Broker將把limit申請下推至Historical進(jìn)程邻辉。當(dāng)排序使用字段不在分組關(guān)鍵字中時陈瘦,此優(yōu)化可能會導(dǎo)致近似結(jié)果的準(zhǔn)確性降低敢靡,因此截汪,在這種情況默認(rèn)禁用此項癣疟。需啟用則在上下文中設(shè)置
    applyLimitPushDownToSegment 如果Broker將下限限制到可查詢的節(jié)點(diǎn)(Historical掏湾,peons)兆龙,則在段掃描期間限制結(jié)果宛官。此上下文屬性可覆蓋Druid.query.groupBy.applyLimitPushDownToSegment媒咳。
  • GroupBy v1配置

    運(yùn)行時屬性:

    屬性 描述 默認(rèn)
    Druid.query.groupBy.maxIntermediateRows 每段分組允許的最大行數(shù)迹缀。這是一個調(diào)整參數(shù)使碾,沒有強(qiáng)加任何限制。相反祝懂,它可能會將合并工作從每個細(xì)分引擎轉(zhuǎn)移到整體合并索引票摇。超過此限制的查詢不會失敗。 50000
    Druid.query.groupBy.maxResults 最大結(jié)果數(shù)砚蓬。超過此限制的查詢將失敗矢门。 500000

    支持的查詢上下文:

    屬性 描述 默認(rèn)
    maxIntermediateRows 用于降低Druid.query.groupBy.maxIntermediateRows的默認(rèn)值。 沒有
    maxResults 用于降低Druid.query.groupBy.maxResults的默認(rèn)值灰蛙。 沒有
    useOffheap 設(shè)置為true可以在合并結(jié)果時以非堆方式存儲聚合祟剔。

基于數(shù)組的結(jié)果行

Druid內(nèi)部始終使用基于數(shù)組的groupBy結(jié)果行表示,但是默認(rèn)情況下摩梧,它在Broker處轉(zhuǎn)換為基于映射的結(jié)果格式物延。為了減少此轉(zhuǎn)換的開銷,如果在查詢上下文resultAsArray中將其設(shè)置為true障本,則結(jié)果也可以直接從Broker基于數(shù)組格式返回教届。

四、掃描查詢(Scan)

Scan查詢以流模式返回查詢結(jié)果驾霜。

除了將簡單的用法(向broker發(fā)送scan查詢)之外案训,還可以將scan查詢直接發(fā)送給Historical或流式攝取任務(wù)。如果要并行檢索大量數(shù)據(jù)粪糙,這將很有用强霎。

{
"queryType": "scan",
"dataSource": "wikipedia",
"resultFormat": "list",
"columns":[],
"intervals": [
    "2013-01-01/2013-01-02"
],
"batchSize":20480,
"limit":3
}
屬性 描述 必要
queryType 設(shè)置查詢類型為時間序列 scan
dataSource 數(shù)據(jù)源
intervals 定義查詢時間范圍。
resultFormat 結(jié)果集格式
filter 過濾器
columns 要掃描的維度和指標(biāo)的字符串?dāng)?shù)組蓉冈。如果保留為空城舞,則返回所有維度和指標(biāo)轩触。
batchSize 返回給客戶端之前緩沖的最大行數(shù)。默認(rèn)為20480
limit 要返回多少行家夺。如果未指定脱柱,將返回所有行。
order 根據(jù)時間戳返回的行的順序拉馋。支持“升序”榨为,“降序”和“無”(默認(rèn))。當(dāng)前煌茴,僅對__time字段中包含該列columns且滿足時間順序部分中概述的要求的查詢才支持“升序”和“降序” 随闺。
legacy 與“scan-query”類似。默認(rèn)屬性設(shè)置Druid.query.scan.legacy蔓腐,默認(rèn)為false矩乐。
context 上下文

當(dāng)resultFormat等于list時,結(jié)果:

[{
    "segmentId" : "wikipedia_editstream_2012-12-29T00:00:00.000Z_2013-01-10T08:00:00.000Z_2013-01-10T08:13:47.830Z_v9",
    "columns" : [
    "timestamp",
    "robot",
    "namespace",
    "anonymous",
    "unpatrolled",
    "page",
    "language",
    "newpage",
    "user",
    "count",
    "added",
    "delta",
    "variation",
    "deleted"
    ],
    "events" : [ {
        "timestamp" : "2013-01-01T00:00:00.000Z",
        "robot" : "1",
        "namespace" : "article",
        "anonymous" : "0",
        "unpatrolled" : "0",
        "page" : "11._korpus_(NOVJ)",
        "language" : "sl",
        "newpage" : "0",
        "user" : "EmausBot",
        "count" : 1.0,
        "added" : 39.0,
        "delta" : 39.0,
        "variation" : 39.0,
        "deleted" : 0.0
    }, {
        "timestamp" : "2013-01-01T00:00:00.000Z",
        "robot" : "0",
        "namespace" : "article",
        "anonymous" : "0",
        "unpatrolled" : "0",
        "page" : "112_U.S._580",
        "language" : "en",
        "newpage" : "1",
        "user" : "MZMcBride",
        "count" : 1.0,
        "added" : 70.0,
        "delta" : 70.0,
        "variation" : 70.0,
        "deleted" : 0.0
    }, {
        "timestamp" : "2013-01-01T00:00:00.000Z",
        "robot" : "0",
        "namespace" : "article",
        "anonymous" : "0",
        "unpatrolled" : "0",
        "page" : "113_U.S._243",
        "language" : "en",
        "newpage" : "1",
        "user" : "MZMcBride",
        "count" : 1.0,
        "added" : 77.0,
        "delta" : 77.0,
        "variation" : 77.0,
        "deleted" : 0.0
    } ]
} ]

當(dāng)resultFormat等于compactedList時回论,結(jié)果:

[{
    "segmentId" : "wikipedia_editstream_2012-12-29T00:00:00.000Z_2013-01-10T08:00:00.000Z_2013-01-10T08:13:47.830Z_v9",
    "columns" : [
    "timestamp", "robot", "namespace", "anonymous", "unpatrolled", "page", "language", "newpage", "user", "count", "added", "delta", "variation", "deleted"
    ],
    "events" : [
    ["2013-01-01T00:00:00.000Z", "1", "article", "0", "0", "11._korpus_(NOVJ)", "sl", "0", "EmausBot", 1.0, 39.0, 39.0, 39.0, 0.0],
    ["2013-01-01T00:00:00.000Z", "0", "article", "0", "0", "112_U.S._580", "en", "1", "MZMcBride", 1.0, 70.0, 70.0, 70.0, 0.0],
    ["2013-01-01T00:00:00.000Z", "0", "article", "0", "0", "113_U.S._243", "en", "1", "MZMcBride", 1.0, 77.0, 77.0, 77.0, 0.0]
    ]
} ]

[1] 時間排序

Scan查詢當(dāng)前只支持對非傳統(tǒng)查詢的時間戳排序散罕。使用時間戳排序?qū)a(chǎn)生的結(jié)果你們盟指定來自于哪一個具體的段。使用時間戳排序需要結(jié)果集限制要少于Druid.query.scan.maxRowsQueuedForOrdering 的行或所有掃描的段少于Druid.query.scan.maxSegmentPartitionsOrderedInMemory分區(qū)時透葛。除非指定了段列表笨使,否則直接發(fā)布到historicals的查詢不支持時間排序。這些限制的原因在于僚害,時間排序的實現(xiàn)使用兩種策略硫椰,如果不去限制的話,它們會消耗過多的堆內(nèi)存萨蚕。這些策略(下面列出)是根據(jù)historicals選擇的靶草,具體取決于查詢結(jié)果集限制和要掃描的段數(shù)。

  • 優(yōu)先級隊列:historicals上的每個段都按順序打開岳遥。每行都添加到有界優(yōu)先級隊列中奕翔,該隊列按時間戳排序。對于超過結(jié)果集限制的每一行浩蓉,具有最早(如果遞減)時間戳或最新(如果遞升)時間戳的行將出隊派继。處理完每一行后,優(yōu)先級隊列的排序內(nèi)容將分批流回給broker捻艳。嘗試將太多的行加載到內(nèi)存中會帶來歷史節(jié)點(diǎn)內(nèi)存不足的風(fēng)險驾窟。該Druid.query.scan.maxRowsQueuedForOrdering屬性通過限制使用時間排序時,查詢結(jié)果集中的行數(shù)來防止這種情況认轨。

  • N向合并:對于每個段绅络,并行打開每個分區(qū)。由于每個分區(qū)的行已經(jīng)按時間排序,因此可以對每個分區(qū)的結(jié)果執(zhí)行n路合并恩急。這種方法不會將整個結(jié)果集持久存儲在內(nèi)存中(例如Priority Queue)杉畜,因為它會從合并函數(shù)返回批次時將其返回。但是衷恭,由于需要為每個分區(qū)打開解壓縮和解碼緩沖區(qū)此叠,嘗試查詢太多分區(qū)也可能導(dǎo)致高內(nèi)存使用。該Druid.query.scan.maxSegmentPartitionsOrderedInMemory限制通過限制使用時間順序時匾荆,隨時打開的分區(qū)的數(shù)量來防止這種情況拌蜘。

二者Druid.query.scan.maxRowsQueuedForOrdering和Druid.query.scan.maxSegmentPartitionsOrderedInMemory是可配置的杆烁,并且可以基于硬件規(guī)格與被查詢的維度數(shù)來調(diào)節(jié)牙丽。也可以使用查詢上下文中的maxRowsQueuedForOrdering和maxSegmentPartitionsOrderedInMemory屬性來覆蓋這些配置屬性。

[2] 傳統(tǒng)模式

Scan查詢支持傳統(tǒng)模式兔魂,該模式旨在與先前的Scan查詢contrib擴(kuò)展協(xié)議兼容烤芦。在傳統(tǒng)模式下,您可以期望以下行為更改:

  • 該__time列返回為"timestamp"而不是"__time"析校。這將優(yōu)先于您可能擁有的其他任何列"timestamp"构罗。
  • __time即使您沒有特別要求,該列也包含在列列表中智玻。
  • 時間戳記以ISO8601時間字符串返回遂唧。
  • 可以通過傳入 "legacy":true 查詢JSON或通過 Druid.query.scan.legacy=true 在Druid進(jìn)程中進(jìn)行設(shè)置來觸發(fā)傳統(tǒng)模式。如果您以前使用的是scan-query contrib擴(kuò)展名吊奢,則最佳遷移方式是在滾動升級過程中激活傳統(tǒng)模式盖彭,然后在升級完成后將其關(guān)閉。

[3] 配置屬性

屬性 描述 取值 默認(rèn)
Druid.query.scan.maxRowsQueuedForOrdering 使用時間排序時返回的最大行數(shù) [1页滚,2147483647]中的整數(shù) 100000
Druid.query.scan.maxSegmentPartitionsOrderedInMemory 使用時間排序時召边,每個historical掃描的最大段數(shù) [1,2147483647]中的整數(shù) 50
Druid.query.scan.legacy 是否應(yīng)為Scan查詢打開傳統(tǒng)模式 是 或 否

[4] 查詢上下文屬性

屬性 描述 取值 默認(rèn)
maxRowsQueuedForOrdering 使用時間排序時返回的最大行數(shù)裹驰。覆蓋同名的config隧熙。 [1,2147483647]中的整數(shù) Druid.query.scan.maxRowsQueuedForOrdering
maxSegmentPartitionsOrderedInMemory 使用時間排序時幻林,每個歷史記錄掃描的最大段數(shù)贞盯。覆蓋同名的config。 [1沪饺,2147483647]中的整數(shù) Druid.query.scan.maxSegmentPartitionsOrderedInMemory

查詢context 的JSON對象:

{
    "maxRowsQueuedForOrdering": 100001,
    "maxSegmentPartitionsOrderedInMemory": 100
}

五躏敢、時間邊界查詢(TimeBoundary)

時間邊界查詢返回數(shù)據(jù)集的最早和最新數(shù)據(jù)點(diǎn)

{
    "queryType" : "timeBoundary",
    "dataSource": "sample_datasource",
    "bound"     : < "maxTime" | "minTime" > # optional, defaults to returning both timestamps if not set
    "filter"    : { "type": "and", "fields": [<filter>, <filter>, ...] } # optional
}

時間邊界查詢包含3個主要部分:

屬性 描述 必要
queryType 設(shè)置查詢類型為時間序列 timeBoundary
dataSource 數(shù)據(jù)源
bound 可選,設(shè)置為maxTime或minTime僅返回最新或最早的時間戳随闽。如果未設(shè)置父丰,默認(rèn)返回兩者
filter 見過濾器
context 參見上下文
[ {
"timestamp" : "2013-05-09T18:24:00.000Z",
"result" : {
    "minTime" : "2013-05-09T18:24:00.000Z",
    "maxTime" : "2013-05-09T18:37:00.000Z"
}
} ]

六、段元數(shù)據(jù)查詢(SegmentMeatadata)

  • 段中所有列的基數(shù)
  • 段中字符串類型列的最小值/最大值
  • 如果段列以平面格式存儲,則估計的字節(jié)大小
  • 段內(nèi)存儲的行數(shù)
  • 該段所覆蓋的區(qū)間
  • 段中所有列的列類型
  • 如果以平面格式存儲蛾扇,則估計的總段字節(jié)大小
  • 段是否累積
  • 段ID
{
"queryType":"segmentMetadata",
"dataSource":"sample_datasource",
"intervals":["2013-01-01/2014-01-01"]
}
屬性 描述 必要
queryType 設(shè)置查詢類型為時間序列 segmentMetadata
dataSource 數(shù)據(jù)源
intervals 定義查詢時間范圍攘烛。
toInclude 在結(jié)果中包括的列。默認(rèn)為所有镀首。
merge 將所有單獨(dú)段的元數(shù)據(jù)結(jié)果合并在一起
context 上下文
analysisTypes 字符串列表坟漱,指定應(yīng)計算哪些列屬性(例如基數(shù),大懈濉)并在結(jié)果中返回芋齿。默認(rèn)為[“ cardinality”,“ interval”成翩,“ minmax”]觅捆,但可以使用段元數(shù)據(jù)查詢config覆蓋。
lenientAggregatorMerge 如果為true麻敌,則合并聚合栅炒。
[ {
"id" : "some_id",
"intervals" : [ "2013-05-13T00:00:00.000Z/2013-05-14T00:00:00.000Z" ],
"columns" : {
    "__time" : { "type" : "LONG", "hasMultipleValues" : false, "size" : 407240380, "cardinality" : null, "errorMessage" : null },
    "dim1" : { "type" : "STRING", "hasMultipleValues" : false, "size" : 100000, "cardinality" : 1944, "errorMessage" : null },
    "dim2" : { "type" : "STRING", "hasMultipleValues" : true, "size" : 100000, "cardinality" : 1504, "errorMessage" : null },
    "metric1" : { "type" : "FLOAT", "hasMultipleValues" : false, "size" : 100000, "cardinality" : null, "errorMessage" : null }
},
"aggregators" : {
    "metric1" : { "type" : "longSum", "name" : "metric1", "fieldName" : "metric1" }
},
"queryGranularity" : {
    "type": "none"
},
"size" : 300000,
"numRows" : 5000000
} ]

維度列的類型為STRING,指標(biāo)列將具有類型FLOAT或LONG或者底層復(fù)雜的類型,如hyperUnique類型术羔。時間戳列的類型為LONG赢赊。

如果該errorMessage字段為非空,則不需要檢查其他的字段因為它們的內(nèi)容是不確定的级历。

只有維度列(即具有type為STRING)的列將具有任何基數(shù)释移。其余列(時間戳記和指標(biāo)列)將顯示基數(shù)為null。

[1] 時間間隔

如果未指定時間間隔寥殖,則查詢將使用默認(rèn)時間間隔玩讳,該時間間隔從最近段的結(jié)束時間開始到之前的可配置時間長度。該默認(rèn)時間段的長度是通過以下方式在Broker配置中設(shè)置的:Druid.query.segmentMetadata.defaultHistory

[2] 3種類型的toInclude對象

  • all

    "toInclude": { "type": "all"}
    
  • none

    "toInclude": { "type": "none"}
    
  • list

    "toInclude": { "type": "list", "columns": [<string list of column names>]}
    

[3] analysisTypes

這是一列屬性扛禽,這些屬性確定有關(guān)列返回的信息量锋边,即要對列執(zhí)行的分析。

默認(rèn)情況下编曼,將使用“cardinality”豆巨,“interval”和“minmax”類型。如果不需要某個屬性掐场,則從此列表中刪除

可以通過以下方式在Broker配置中設(shè)置默認(rèn)分析類型: Druid.query.segmentMetadata.defaultAnalysisTypes

列分析的類型

  • cardinality

    cardinality結(jié)果將返回每一列的估計基數(shù)下限往扔。僅與維列相關(guān)。
    
  • minmax

    每列的估計最小值/最大值熊户。僅與維列相關(guān)萍膛。
    
  • size

    結(jié)果中將包含估計的總段字節(jié)大小
    
  • intervals

    結(jié)果中將包含與查詢段關(guān)聯(lián)的間隔列表
    
  • timestampSpec

    結(jié)果中將包含存儲在段中的數(shù)據(jù)的timestampSpec
    
  • queryGranularity

    結(jié)果中將包含存儲在段中的數(shù)據(jù)的查詢粒度
    
  • aggregators

    結(jié)果中將包含可用于查詢指標(biāo)列的聚合器列表
    合并可以嚴(yán)格也可以寬松
    結(jié)果的形式是列名到聚合器的映射
    
  • rollup

    結(jié)果為 true/false/null
    

[4] lenientAggregatorMerge

如果某些段的聚合器未知,或者兩個段的同一列使用不兼容的聚合器(例如嚷堡,longSum更改為doubleSum)蝗罗,則跨段的聚合器元數(shù)據(jù)之間可能會發(fā)生沖突艇棕。

聚合器可以嚴(yán)格合并(默認(rèn))或?qū)捤珊喜ⅰMㄟ^嚴(yán)格合并串塑,如果存在任何段的聚合器未知或任何類型的沖突沼琉,則合并的聚合器列表將為null。通過寬松的合并桩匪,將忽略具有未知聚合器的段打瘪,并且聚合器之間的沖突只會使該特定列的聚合器無效。

特別是在寬大合并的情況下傻昙,單個列的聚合器可能是null闺骚。嚴(yán)格合并不會發(fā)生這種情況。

七妆档、數(shù)據(jù)源元數(shù)據(jù)查詢(DatasourceMeatadata)

數(shù)據(jù)源的元數(shù)據(jù)查詢僻爽,返回數(shù)據(jù)源的元數(shù)據(jù)信息。

{
    "queryType" : "dataSourceMetadata",
    "dataSource": "sample_datasource"
}

數(shù)據(jù)源的元數(shù)據(jù)查詢包含兩個主要部分:

屬性 描述 必要
queryType 設(shè)置查詢類型為時間序列 dataSourceMetadata
dataSource 數(shù)據(jù)源
context 參見上下文
[ {
"timestamp" : "2013-05-09T18:24:00.000Z",
"result" : {
    "maxIngestedEventTime" : "2013-05-09T18:24:09.007Z"
}
} ]

八过吻、搜索查詢(Search)

搜索查詢返回與搜索規(guī)范匹配

{
"queryType": "search",
"dataSource": "sample_datasource",
"granularity": "day",
"searchDimensions": [
    "dim1",
    "dim2"
],
"query": {
    "type": "insensitive_contains",
    "value": "Ke"
},
"sort" : {
    "type": "lexicographic"
},
"intervals": [
    "2013-01-01T00:00:00.000/2013-01-03T00:00:00.000"
]
}
屬性 描述 必要
queryType 設(shè)置查詢類型為時間序列 search
dataSource 數(shù)據(jù)源
granularity 定義查詢結(jié)果的粒度
filter 過濾器
limit 限制結(jié)果數(shù)量进泼。默認(rèn)值為無限制。
intervals 定義查詢時間范圍纤虽。
searchDimensions 要進(jìn)行搜索的維度。默認(rèn)在所有維度上進(jìn)行绞惦。 沒有
query 查詢
sort 指定排序字段 字典(默認(rèn))逼纸,字母,數(shù)字等济蝉。 沒有
context 上下文 沒有
[
{
    "timestamp": "2013-01-01T00:00:00.000Z",
    "result": [
    {
        "dimension": "dim1",
        "value": "Ke$ha",
        "count": 3
    },
    {
        "dimension": "dim2",
        "value": "Ke$haForPresident",
        "count": 1
    }
    ]
},
{
    "timestamp": "2013-01-02T00:00:00.000Z",
    "result": [
    {
        "dimension": "dim1",
        "value": "SomethingThatContainsKe",
        "count": 1
    },
    {
        "dimension": "dim2",
        "value": "SomethingElseThatContainsKe",
        "count": 2
    }
    ]
}
]

[1] 實施細(xì)節(jié)

可以使用兩種不同的策略來執(zhí)行搜索查詢杰刽。默認(rèn)策略由Broker上的“ Druid.query.search.searchStrategy”運(yùn)行時屬性確定⊥趼耍可以在查詢上下文中使用“ searchStrategy”來覆蓋它贺嫂。如果既未設(shè)置上下文字段也未設(shè)置屬性,則將使用“ useIndexes”策略雁乡。

  • “useIndexes”策略首先根據(jù)搜索維度對位圖索引的支持將其分為兩類第喳。然后,它將useIndexes策略和基cursorOnly策略分別應(yīng)用于支持位圖和其他維度的維組踱稍。useIndexes策略用于搜索查詢處理曲饱。對于每個維度,它會讀取每個維度值的位圖索引珠月,評估搜索謂詞扩淀,最后檢查時間間隔和篩選謂詞。useIndexes策略對于大基數(shù)的搜索維度性能較低啤挎,這意味著大多數(shù)搜索維值都是唯一的驻谆。

  • “cursorOnly”策略生成基于基礎(chǔ)指針計劃。該計劃創(chuàng)建一個指針標(biāo),該指針從queryableIndexSegment中讀取一行胜臊,然后評估搜索的詞氛谜。如果某些過濾器支持位圖索引,則指針只能讀取滿足這些過濾器的行区端,從而節(jié)省了I/O成本值漫。但是,對于低選擇性的過濾器织盼,它可能會很慢杨何。

  • “auto”策略使用基于搜索成本的計劃程序,來選擇最佳搜索策略沥邻。它評估useIndexes和cursorOnly兩種策略的成本危虱,并選擇最佳的計劃。當(dāng)前唐全,由于成本估算的開銷埃跷,默認(rèn)情況下未啟用它。

[2] 服務(wù)器配置

屬性 描述 默認(rèn)
Druid.query.search.searchStrategy 默認(rèn)搜索查詢策略邮利。 useIndexes

[3] 查詢上下文

屬性 描述
searchStrategy 覆蓋Druid.query.search.searchStrategy此屬性值弥雹。

九、選擇查詢(Select)

從當(dāng)前新版本開始延届,刪除select的查詢使用Scan查詢代替剪勿,該查詢可提高內(nèi)存使用率和性能。這解決了用戶在選擇查詢中遇到Druid內(nèi)存不足或速度變慢的問題方庭。

Scan查詢具有不同的語法厕吉,但支持Select查詢的許多功能,包括時間排序和限制械念。Scan查詢不包括Select查詢的分頁功能头朱;但是,在許多情況下龄减,使用Scan不需要分頁项钮,因為它能夠在一個調(diào)用中返回幾乎無限數(shù)量的結(jié)果。

十欺殿、多值維度查詢(Multi-value dimensions)

Druid支持多值維度查詢寄纵。當(dāng)輸入字段包含的值是數(shù)組而不是單個值(例如JSON數(shù)組或包含一個或多個listDelimiter 字符的TSV字段)時,將生成這些字段脖苏。

當(dāng)多值維度用作分組依據(jù)的維度時程拭,本文檔描述了groupBy(topN具有類似行為)查詢的行為。有關(guān)內(nèi)部表示形式的詳細(xì)信息棍潘,請參見分段中的多值列一 節(jié)恃鞋。本文檔中的示例采用本機(jī)Druid查詢的形式崖媚。有關(guān)在SQL中使用多值字符串維的詳細(xì)信息,請參閱Druid SQL文檔恤浪。

[1] 查詢多值維度

假設(shè)您有一個數(shù)據(jù)源畅哑,該數(shù)據(jù)源的段中包含以下行,且其多值維度稱為tags水由。

{"timestamp": "2011-01-12T00:00:00.000Z", "tags": ["t1","t2","t3"]}  #row1
{"timestamp": "2011-01-13T00:00:00.000Z", "tags": ["t3","t4","t5"]}  #row2
{"timestamp": "2011-01-14T00:00:00.000Z", "tags": ["t5","t6","t7"]}  #row3
{"timestamp": "2011-01-14T00:00:00.000Z", "tags": []}                #row4

[2] Filter

所有查詢類型以及經(jīng)過過濾的聚合器都可以對多值維度進(jìn)行過濾荠呐。過濾器在多值維度上遵循以下規(guī)則:

  • 如果多值維度的任何值與過濾器匹配,則值過濾器(例如“selector”砂客,“bound”和“in”)將與一行匹配泥张。
  • 如果維度有任何重疊,則“列比較”過濾器將匹配一行鞠值。
  • 匹配null或""(空字符串)的值過濾器將匹配多值維度中的空單元格媚创。
  • 邏輯表達(dá)式過濾器的行為與在單值維度上的行為相同:如果所有基礎(chǔ)過濾器均與該行匹配,則“and”匹配該行彤恶;如果任何基礎(chǔ)過濾器匹配該行钞钙,則“or”匹配該行;如果基礎(chǔ)過濾器與該行不匹配声离,則“not”與該行匹配芒炼。

例如,此“or”過濾器將匹配上面數(shù)據(jù)集的row1和row2抵恋,但不匹配row3:

{
   "type": "or",
   "fields": [
   {
       "type": "selector",
       "dimension": "tags",
       "value": "t1"
   },
   {
       "type": "selector",
       "dimension": "tags",
       "value": "t3"
   }
   ]
}

此“and”過濾器將僅匹配上述數(shù)據(jù)集的row1:

{
    "type": "and",
    "fields": [
    {
        "type": "selector",
        "dimension": "tags",
        "value": "t1"
    },
    {
        "type": "selector",
        "dimension": "tags",
        "value": "t3"
    }
    ]
}

此“selector”過濾器將匹配以上數(shù)據(jù)集的row4:

{
    "type": "selector",
    "dimension": "tags",
    "value": null
}

[3] Group

topN和groupBy查詢可以對多值維度進(jìn)行分組焕议。在對多值維度進(jìn)行分組時,匹配行中的所有值將用于為每個值生成一組弧关。可以認(rèn)為這等效于許多SQL語言支持UNNEST的ARRAY類型上使用的運(yùn)算符唤锉。這意味著查詢有可能返回的行多于結(jié)果行數(shù)世囊。例如,一個topn的維度列tags與filter "t1" AND "t3"將只ROW1匹配窿祥,并與三個組生成結(jié)果:t1株憾,t2,和t3晒衩。如果只需要包含與filter匹配的值嗤瞎,則可以使用filter的 DimensionSpec。這也可以提高性能听系。

不使用filter的GroupBy查詢

{
    "queryType": "groupBy",
    "dataSource": "test",
    "intervals": [
    "1970-01-01T00:00:00.000Z/3000-01-01T00:00:00.000Z"
    ],
    "granularity": {
    "type": "all"
    },
    "dimensions": [
    {
        "type": "default",
        "dimension": "tags",
        "outputName": "tags"
    }
    ],
    "aggregations": [
    {
        "type": "count",
        "name": "count"
    }
    ]
}

返回結(jié)果贝奇。

[
    {
    "timestamp": "1970-01-01T00:00:00.000Z",
    "event": {
        "count": 1,
        "tags": "t1"
    }
    },
    {
    "timestamp": "1970-01-01T00:00:00.000Z",
    "event": {
        "count": 1,
        "tags": "t2"
    }
    },
    {
    "timestamp": "1970-01-01T00:00:00.000Z",
    "event": {
        "count": 2,
        "tags": "t3"
    }
    },
    {
    "timestamp": "1970-01-01T00:00:00.000Z",
    "event": {
        "count": 1,
        "tags": "t4"
    }
    },
    {
    "timestamp": "1970-01-01T00:00:00.000Z",
    "event": {
        "count": 2,
        "tags": "t5"
    }
    },
    {
    "timestamp": "1970-01-01T00:00:00.000Z",
    "event": {
        "count": 1,
        "tags": "t6"
    }
    },
    {
    "timestamp": "1970-01-01T00:00:00.000Z",
    "event": {
        "count": 1,
        "tags": "t7"
    }
    }
]

使用selector查詢使用filter的結(jié)果進(jìn)行GroupBy查詢

{
    "queryType": "groupBy",
    "dataSource": "test",
    "intervals": [
    "1970-01-01T00:00:00.000Z/3000-01-01T00:00:00.000Z"
    ],
    "filter": {
    "type": "selector",
    "dimension": "tags",
    "value": "t3"
    },
    "granularity": {
    "type": "all"
    },
    "dimensions": [
    {
        "type": "default",
        "dimension": "tags",
        "outputName": "tags"
    }
    ],
    "aggregations": [
    {
        "type": "count",
        "name": "count"
    }
    ]
}

返回結(jié)果。

[
    {
    "timestamp": "1970-01-01T00:00:00.000Z",
    "event": {
        "count": 1,
        "tags": "t1"
    }
    },
    {
    "timestamp": "1970-01-01T00:00:00.000Z",
    "event": {
        "count": 1,
        "tags": "t2"
    }
    },
    {
    "timestamp": "1970-01-01T00:00:00.000Z",
    "event": {
        "count": 2,
        "tags": "t3"
    }
    },
    {
    "timestamp": "1970-01-01T00:00:00.000Z",
    "event": {
        "count": 1,
        "tags": "t4"
    }
    },
    {
    "timestamp": "1970-01-01T00:00:00.000Z",
    "event": {
        "count": 1,
        "tags": "t5"
    }
    }
]

您可能會驚訝地發(fā)現(xiàn)結(jié)果中包含“t1”靠胜,“t2”掉瞳,“t4”和“t5”毕源。發(fā)生這種情況是因為查詢過濾器在分解前應(yīng)用于行。對于多值維度陕习,“t3”的選擇器過濾器將匹配row1和row2霎褐,然后進(jìn)行分解。如果多個值中的任何單個值與查詢過濾器匹配该镣,則查詢過濾器將匹配一行冻璃。

使用selector查詢過濾器和“維度”屬性中的其他過濾器進(jìn)行GroupBy查詢,要解決上述問題并僅獲取返回的“t3”行,則必須使用“過濾的尺寸規(guī)格”损合,如下面的查詢所示省艳。

{
    "queryType": "groupBy",
    "dataSource": "test",
    "intervals": [
    "1970-01-01T00:00:00.000Z/3000-01-01T00:00:00.000Z"
    ],
    "filter": {
    "type": "selector",
    "dimension": "tags",
    "value": "t3"
    },
    "granularity": {
    "type": "all"
    },
    "dimensions": [
    {
        "type": "listFiltered",
        "delegate": {
        "type": "default",
        "dimension": "tags",
        "outputName": "tags"
        },
        "values": ["t3"]
    }
    ],
    "aggregations": [
    {
        "type": "count",
        "name": "count"
    }
    ]
}

返回結(jié)果。

[
    {
    "timestamp": "1970-01-01T00:00:00.000Z",
    "event": {
        "count": 2,
        "tags": "t3"
    }
    }
]

對于groupBy查詢塌忽,使用具有spec的結(jié)果可能會得到類似的結(jié)果拍埠,但是使用過濾后的DimensionSpec會更加有效,因為這是在查詢處理管道中的最低級別的應(yīng)用土居。

十一枣购、查找查詢(Lookups)

Lookups是Druid中的一個概念,其中(可選)將維值替換為新值擦耀,從而實現(xiàn)類似聯(lián)接的功能棉圈。在Druid中應(yīng)用查找類似于在數(shù)據(jù)倉庫中加入維度表。就這些文檔而言眷蜓,“key”是指要匹配的值分瘾,“value”是指其替換值。因此吁系,如果您想映射 appid-12345到德召,Super Mega Awesome App則鍵為appid-12345,值將為 Super Mega Awesome App汽纤。

值得注意的是上岗,查找不僅支持將鍵一對一映射到唯一值(例如國家/地區(qū)代碼和國家/地區(qū)名稱)的用例奈揍,而且還支持將多個ID映射到同一值(例如跷究,多個應(yīng)用程序ID)的用例。映射到單個客戶經(jīng)理传轰。當(dāng)查詢是一對一的時背传,Druid可以在查詢時應(yīng)用其他優(yōu)化呆瞻。

查找沒有歷史記錄。他們總是使用當(dāng)前數(shù)據(jù)径玖。這意味著痴脾,如果某個特定應(yīng)用程序ID的主要客戶經(jīng)理發(fā)生了變化,并且您發(fā)出了一個查詢挺狰,以查找存儲該應(yīng)用程序ID與客戶經(jīng)理的關(guān)系明郭,則它將返回該應(yīng)用程序ID的當(dāng)前客戶經(jīng)理买窟。

如果您需要數(shù)據(jù)時間范圍敏感的查找,那么當(dāng)前在查詢時不動態(tài)支持這種用例薯定,并且此類數(shù)據(jù)屬于原始的非規(guī)范化數(shù)據(jù)始绍,供在Druid中使用。

可以在查詢時將很小的查找(鍵的數(shù)量在幾十到幾百的數(shù)量級上)作為“映射”查找(根據(jù)維度規(guī)格)進(jìn)行傳遞话侄。

其他查找類型也可以作為擴(kuò)展使用亏推,包括:

  • 通過lookups-cached-global從本地文件,遠(yuǎn)程URI或JDBC全局緩存的查找年堆。
  • 通過kafka-extraction-namespace從Kafka主題全局緩存的查找吞杭。

[1] 查詢語法

在Druid SQL中,可以使用LOOKUP函數(shù)查詢查詢

SELECT LOOKUP(column_name, 'lookup-name'), COUNT(*) FROM datasource GROUP BY 1

在本機(jī)json查詢中变丧,可以使用維度列或擴(kuò)展查詢芽狗。

[2] 查詢執(zhí)行

當(dāng)查詢執(zhí)行涉及到的聚合時,Druid可以決定在掃描和聚合行時應(yīng)用查詢痒蓬,還是在聚合完成后應(yīng)用查詢童擎。聚合完成后應(yīng)用查找更為有效,因此Druid會這樣做攻晒。Druid通過檢查查找是否標(biāo)記為“injective”來決定顾复。通常,應(yīng)該為任何自然一對一的查找設(shè)置此屬性鲁捏,以允許Druid盡可能快地運(yùn)行查詢芯砸。

內(nèi)射式查找應(yīng)包括可能顯示在數(shù)據(jù)集中的所有可能的鍵,并且還應(yīng)將所有鍵映射成唯一值给梅。這很重要假丧,因為非注入式查找可能會將不同的鍵映射到相同的值,這必須在聚合過程中加以考慮动羽,以免查詢結(jié)果包含兩個應(yīng)該聚合為一個的結(jié)果值虎谢。

  • 此查詢是內(nèi)射性的(假定它包含數(shù)據(jù)中所有可能的鍵):

    1 -> Foo
    2 -> Bar
    3 -> Billy
    
  • 但有一個不是,因為“ 2”和“ 3”都映射到相同的鍵:

    1 -> Foo
    2 -> Bar
    3 -> Bar
    

要告訴Druid您的lookup是已經(jīng)配置的 "injective":true曹质,必須在查找配置中指定。Druid不會自動檢測到這一點(diǎn)擎场。

[3] 動態(tài)配置

動態(tài)查找配置是一項實驗功能羽德。不再支持靜態(tài)配置。以下內(nèi)容記錄了可通過Coordinator訪問的群集范圍配置的行為迅办。通過服務(wù)器“層”的概念傳遞配置宅静。“層”定義為一組接收查詢站欺,一組查詢的服務(wù)姨夹。例如纤垂,您可能將所有“歷史記錄”作為的一部分__default,而“Peons”則作為其任務(wù)所使用的數(shù)據(jù)源的各個層的一部分磷账。查找的層完全獨(dú)立于歷史層峭沦。

通過以下URI模板使用JSON訪問這些配置

http://<COORDINATOR_IP>:<PORT>/Druid/coordinator/v1/lookups/config/{tier}/{id}

假定以下所有URI都已http://<COORDINATOR_IP>:<PORT>添加。

如果你以前從來沒有配置lookup逃糟,您必須張貼一個空的JSON對象{}來/Druid/coordinator/v1/lookups/config初始化配置吼鱼。

將返回以下結(jié)果之一:

  • 404, 如果找不到資源
  • 400,如果請求的格式有問題
  • 202, 如果請求被異步接受(POST和DELETE)
  • 200绰咽,如果請求成功(僅GET)

[4] 配置傳播行為

配置由Coordinator傳播到查詢服務(wù)進(jìn)程(Broker/Router/Peon/Historical)菇肃。查詢服務(wù)流程具有內(nèi)部API,用于管理流程上的查找取募,并且由Coordinator使用琐谤。Coordinator會定期檢查是否有任何進(jìn)程需要加載/刪除,查找并適當(dāng)?shù)馗滤鼈儭?/p>

單個查詢服務(wù)過程只能同時處理2個查找配置傳播請求。應(yīng)用此限制是為了防止查找處理占用過多的服務(wù)器HTTP連接玩敏。

[5] 用于配置查找的API

批量更新

可以通過將JSON對象來批量更新查找/Druid/coordinator/v1/lookups/config

{
    "<tierName>": {
        "<lookupName>": {
            "version": "<version>",
            "lookupExtractorFactory": {
            "type": "<someExtractorFactoryType>",
            "<someExtractorField>": "<someExtractorValue>"
            }
        }
    }
}

“version”是由用戶分配的任意字符串斗忌,當(dāng)對現(xiàn)有查找進(jìn)行更新時,用戶將需要指定詞典上更高的版本聊品。

配置示例

{
    "__default": {
    "country_code": {
        "version": "v0",
        "lookupExtractorFactory": {
        "type": "map",
        "map": {
            "77483": "United States"
        }
        }
    },
    "site_id": {
        "version": "v0",
        "lookupExtractorFactory": {
        "type": "cachedNamespace",
        "extractionNamespace": {
            "type": "jdbc",
            "connectorConfig": {
            "createTables": true,
            "connectURI": "jdbc:mysql:\/\/localhost:3306\/Druid",
            "user": "Druid",
            "password": "diurd"
            },
            "table": "lookupTable",
            "keyColumn": "country_id",
            "valueColumn": "country_name",
            "tsColumn": "timeColumn"
        },
        "firstCacheTimeout": 120000,
        "injective": true
        }
    },
    "site_id_customer1": {
        "version": "v0",
        "lookupExtractorFactory": {
        "type": "map",
        "map": {
            "847632": "Internal Use Only"
        }
        }
    },
    "site_id_customer2": {
        "version": "v0",
        "lookupExtractorFactory": {
        "type": "map",
        "map": {
            "AHF77": "Home"
        }
        }
    }
    },
    "realtime_customer1": {
    "country_code": {
        "version": "v0",
        "lookupExtractorFactory": {
        "type": "map",
        "map": {
            "77483": "United States"
        }
        }
    },
    "site_id_customer1": {
        "version": "v0",
        "lookupExtractorFactory": {
        "type": "map",
        "map": {
            "847632": "Internal Use Only"
        }
        }
    }
    },
    "realtime_customer2": {
    "country_code": {
        "version": "v0",
        "lookupExtractorFactory": {
        "type": "map",
        "map": {
            "77483": "United States"
        }
        }
    },
    "site_id_customer2": {
        "version": "v0",
        "lookupExtractorFactory": {
        "type": "map",
        "map": {
            "AHF77": "Home"
        }
        }
    }
    }
}

映射中的所有條目將更新成現(xiàn)有條目飞蹂。沒有的條目將被刪除。

[6] 更新查詢

通過POST請求一個特定的查找提取器工廠/Druid/coordinator/v1/lookups/config/{tier}/{id}將更新該特定的提取器工廠翻屈。

示例請求/Druid/coordinator/v1/lookups/config/realtime_customer1/site_id_customer1

{
    "version": "v1",
    "lookupExtractorFactory": {
    "type": "map",
    "map": {
        "847632": "Internal Use Only"
    }
    }
}

這將用上面定義的site_id_customer1替換查找到的realtime_customer1陈哑。

  • 獲取所有查詢

    GET請求到/Druid/coordinator/v1/lookups/config/all將返回所有已知查找的功能和所有層次。

  • 查找

    通過GET特定的查找提取器工廠來完成/Druid/coordinator/v1/lookups/config/{tier}/{id}

    示例:一個GET請求 /Druid/coordinator/v1/lookups/config/realtime_customer2/site_id_customer2應(yīng)該返回

    {
      "version": "v1",
      "lookupExtractorFactory": {
        "type": "map",
        "map": {
          "AHF77": "Home"
        }
      }
    }
    
  • 刪除查詢

    DELETE請求/Druid/coordinator/v1/lookups/config/{tier}/{id}也可以從集群刪除查找伸眶。如果是該層中的最后一次查找惊窖,則該層也將被刪除。

  • 刪除層

    DELETE請求/Druid/coordinator/v1/lookups/config/{tier}會從集群中刪除該層厘贼。

  • 層列表名稱

    GET請求/Druid/coordinator/v1/lookups/config將在動態(tài)配置返回已知層名稱的列表界酒。除了動態(tài)配置中已知的層之外,要發(fā)現(xiàn)集群中當(dāng)前活動的層的列表嘴秸,設(shè)置discover=true 可以按照來添加參數(shù)/Druid/coordinator/v1/lookups/config?discover=true

  • 列出查詢名稱

    GET請求/Druid/coordinator/v1/lookups/config/{tier}會返回已知的查找該層級名稱列表毁欣。

    這些端點(diǎn)可用于獲取已配置的查找到使用諸如“歷史記錄”之類的查找的進(jìn)程的傳播狀態(tài)。

[7] 查找狀態(tài)的API

  • 列出所有查找的加載狀態(tài)

    GET /Druid/coordinator/v1/lookups/status帶有可選的查詢參數(shù)detailed岳掐。

  • 列出層中查找的負(fù)載狀態(tài)

    GET /Druid/coordinator/v1/lookups/status/{tier}帶有可選的查詢參數(shù)detailed凭疮。

  • 列出單次查找的加載狀態(tài)

    GET /Druid/coordinator/v1/lookups/status/{tier}/{lookup}帶有可選的查詢參數(shù)detailed。

  • 列出所有進(jìn)程的查找狀態(tài)

    GET /Druid/coordinator/v1/lookups/nodeStatus帶有discover用于從Zookeeper發(fā)現(xiàn)層的可選查詢參數(shù)或列出的已配置查找層串述。

  • 列出層中進(jìn)程的查找狀態(tài)

    GET /Druid/coordinator/v1/lookups/nodeStatus/{tier}

  • 列出單個進(jìn)程的查找狀態(tài)

    GET /Druid/coordinator/v1/lookups/nodeStatus/{tier}/{host:port}

[8] 內(nèi)部API

Peon执解,Router,Broker和Historical進(jìn)程都可以使用查找配置纲酗。這些流程使用一個內(nèi)部API來從list/load/drop其查找內(nèi)容/Druid/listen/v1/lookups衰腌。這些返回值與集群范圍的動態(tài)配置遵循相同的約定新蟆。以下請求示例可用于調(diào)試,但不能用于其他右蕊。

  • 獲取查詢

    一個GET以處理在/Druid/listen/v1/lookups將返回所有在進(jìn)程當(dāng)前活躍查詢的JSON地圖琼稻。返回值將是查找到其提取器工廠的json映射。

    {
      "site_id_customer2": {
        "version": "v1",
        "lookupExtractorFactory": {
          "type": "map",
          "map": {
            "AHF77": "Home"
          }
        }
      }
    }
    
  • 查找

    GET請求/Druid/listen/v1/lookups/some_lookup_name將返回LookupExtractorFactory由確定的查找some_lookup_name尤泽。返回值將是工廠的json表示形式欣簇。

    {
      "version": "v1",
      "lookupExtractorFactory": {
        "type": "map",
        "map": {
          "AHF77": "Home"
        }
      }
    }
    
  • 配置

    要將Broker/Router/Historical/Peon配置為查找層的一部分,請使用Druid.zk.paths.lookupTier屬性坯约。

    屬性 描述 默認(rèn)
    Druid.lookup.lookupTier 查詢層熊咽。這獨(dú)立于其他層。 __default
    Druid.lookup.lookupTierIsDatasource 對于諸如,為服務(wù)任務(wù)編制索引之類的事情闹丐,數(shù)據(jù)源將在任務(wù)運(yùn)行時的屬性中傳遞横殴。此選項從與任務(wù)數(shù)據(jù)源相同的值中獲取tierName。建議將其用作索引服務(wù)的Peon選項(如果有的話)卿拴。如果為true衫仑,則Druid.lookup.lookupTier不得指定 "false"

    要動態(tài)配置管理器的行為,請在Coordinator上使用以下屬性:

    屬性 描述 默認(rèn)
    Druid.manager.lookups.hostTimeout 超時(以毫秒為單位堕花,用于處理請求 2000(2秒)
    Druid.manager.lookups.allHostTimeout 超時(以毫秒為單位)以完成所有進(jìn)程的查找管理文狱。 900000(15分鐘)
    Druid.manager.lookups.period 在管理周期之間暫停多長時間 120000(2分鐘)
    Druid.manager.lookups.threadPoolSize 可以同時管理的服務(wù)進(jìn)程數(shù) 10
  • 重啟時保存配置

    可以在重新啟動之前保存配置,這樣一來缘挽,進(jìn)程將不必等待協(xié)調(diào)器操作重新填充其查找瞄崇。為此,設(shè)置以下屬性:

    屬性 描述 默認(rèn)
    Druid.lookup.snapshotWorkingDir 用于存儲當(dāng)前查找配置快照的工作路徑壕曼,將此屬性保留為null將禁用快照/引導(dǎo)實用程序 null
    Druid.lookup.enableLookupSyncOnStartup 啟動時使用Coordinator啟用查找同步過程苏研。可查詢的進(jìn)程將從Coordinator獲取并加載查找腮郊,而不是等待Coordinator為其加載查找摹蘑。如果集群中未配置任何查找,則用戶可以選擇禁用此選項轧飞。 true
    Druid.lookup.numLookupLoadingThreads 啟動時用于并行加載查找的線程數(shù)衅鹿。啟動完成后,該線程池將被銷毀过咬。在JVM的生存期內(nèi)不保留它 可用處理器/2
    Druid.lookup.coordinatorFetchRetries 在啟動時同步期間塘安,嘗試重試幾次以從Coordinator獲取查找bean列表。 3
    Druid.lookup.lookupStartRetries 在啟動時同步或運(yùn)行時中援奢,嘗試重試多少次才能啟動每個查找。 3
    Druid.lookup.coordinatorRetryDelay 啟動時同步期間忍捡,兩次重試之間的延遲時間(以毫秒為單位)集漾,以從Coordinator中獲取查找列表切黔。 60_000

[9] 內(nèi)省查找

如果查找類型實現(xiàn),則Broker提供用于查找自省的API LookupIntrospectHandler具篇。

GET請求/Druid/v1/lookups/introspect/{lookupId}將返回完整值纬霞。

  • 如:GET /Druid/v1/lookups/introspect/nato-phonetic

    {
        "A": "Alfa",
        "B": "Bravo",
        "C": "Charlie",
        ...
        "Y": "Yankee",
        "Z": "Zulu",
        "-": "Dash"
    }
    

Key列表可以通過檢索GET到/Druid/v1/lookups/introspect/{lookupId}/keys

  • 如:GET /Druid/v1/lookups/introspect/nato-phonetic/keys

    [
        "A",
        "B",
        "C",
        ...
        "Y",
        "Z",
        "-"
    ]
    

GET請求/Druid/v1/lookups/introspect/{lookupId}/values"將返回值列表。

  • 如:GET /Druid/v1/lookups/introspect/nato-phonetic/values

    [
        "Alfa",
        "Bravo",
        "Charlie",
        ...
        "Yankee",
        "Zulu",
        "Dash"
    ]
    

十二驱显、Join查詢(Joins)

Druid對通過查詢時間查找進(jìn)行聯(lián)接的支持有限诗芜。查詢時查找的常見用例是將一個維度值(例如,字符串ID)替換為另一個值(例如埃疫,人類可讀的字符串值)伏恐。這類似于星形模式連接。

Druid尚未完全支持聯(lián)接栓霜。盡管Druid的存儲格式允許實現(xiàn)連接(對于作為維包括的列翠桦,不存在保真度的損失),但由于以下原因胳蛮,尚未完全實現(xiàn)對連接的完全支持:

  • 根據(jù)我們的專業(yè)經(jīng)驗销凑,擴(kuò)展連接查詢一直是使用分布式數(shù)據(jù)庫的一個長期瓶頸。
  • 與管理大量并發(fā)仅炊,連接繁重的工作負(fù)載所預(yù)期的問題相比斗幼,功能上的增量收益被認(rèn)為價值不高。
  • 聯(lián)接查詢本質(zhì)上是基于一組共享鍵合并兩個或更多數(shù)據(jù)流抚垄。我們知道的聯(lián)接查詢的主要高級策略是基于哈希的策略或排序合并策略蜕窿。基于散列的策略要求除了一個數(shù)據(jù)集外督勺,其他所有數(shù)據(jù)集都可以像散列表一樣使用渠羞,然后對“主”流中的每一行對該散列表執(zhí)行查找操作。排序合并策略假定每個流按連接鍵進(jìn)行排序智哀,因此允許流的增量連接次询。但是,這些策略中的每一種都需要以排序的順序或哈希表的形式實現(xiàn)一定數(shù)量的流瓷叫。

當(dāng)聯(lián)接的所有側(cè)面都是非常大的表(> 10億條記錄)時屯吊,要實現(xiàn)預(yù)聯(lián)接流,就需要進(jìn)行復(fù)雜的分布式內(nèi)存管理摹菠。我們針對高并發(fā)盒卸,多租戶工作負(fù)載這一事實,只會加劇內(nèi)存管理的復(fù)雜性次氨。

十三蔽介、多租戶(Multitenancy considerations)

Druid通常用于增強(qiáng)面向用戶的數(shù)據(jù)應(yīng)用程序,而多租戶是其中的重要要求。本文檔概述了Druid的多租戶存儲和查詢功能虹蓄。

[1] 共享的數(shù)據(jù)源還是每個租戶的數(shù)據(jù)源犀呼?

數(shù)據(jù)源與數(shù)據(jù)庫表是等效的。多租戶工作負(fù)載可以為每個租戶使用單獨(dú)的數(shù)據(jù)源薇组,也可以使用“tenant_id”維護(hù)在多個租戶之間共享一個或多個數(shù)據(jù)源外臂。在確定要要設(shè)置的租戶和數(shù)據(jù)源的映射關(guān)系時,要考慮好每一種設(shè)置的優(yōu)缺點(diǎn)律胀。

[2] 每個租戶的數(shù)據(jù)源的優(yōu)點(diǎn):

  • 每個數(shù)據(jù)源可以具有自己的架構(gòu)宋光,自己寫數(shù)據(jù),自己的分區(qū)規(guī)則以及自己的數(shù)據(jù)加載和到期規(guī)則炭菌。
  • 查詢可以更快罪佳,因為要檢查典型租戶的查詢的段將更少。
  • 您將獲得最大的靈活性娃兽。

[3] 共享數(shù)據(jù)源的優(yōu)點(diǎn):

  • 每個數(shù)據(jù)源都需要使用自己的JVM進(jìn)行實時索引菇民。
  • 每個數(shù)據(jù)源都需要自己的YARN資源才能用于Hadoop批處理作業(yè)。
  • 每個數(shù)據(jù)源在磁盤上都需要其自己的段文件投储。
  • 由于這些原因第练,擁有大量的小型數(shù)據(jù)源可能是浪費(fèi)資源的。

一種折衷辦法是使用多個數(shù)據(jù)源玛荞,但使用數(shù)量少于租戶娇掏。例如,您可能有一些帶有分區(qū)規(guī)則A的租戶勋眯,有些帶有分區(qū)規(guī)則B的租戶婴梧;您可以使用兩個數(shù)據(jù)源,并在兩個數(shù)據(jù)源之間拆分租戶客蹋。

[4] 對共享數(shù)據(jù)源進(jìn)行分區(qū)

如果您的多租戶群集使用共享數(shù)據(jù)源塞蹭,則大多數(shù)查詢可能會在“tenant_id”維度上進(jìn)行過濾。如果租戶對數(shù)據(jù)進(jìn)行了很好的分區(qū)讶坯,則這類查詢的效果最佳番电。有幾種方法可以完成此操作。

  • 使用批索引辆琅,您可以使用一維分區(qū)按tenant_id對數(shù)據(jù)進(jìn)行分區(qū)漱办。Druid總是按時間先分區(qū),但是每個時間段內(nèi)的次分區(qū)將在tenant_id上婉烟。
  • 使用實時索引娩井,您可以通過調(diào)整發(fā)送到Druid的流來實現(xiàn)。例如似袁,如果您使用的是Kafka洞辣,則可以讓您的Kafka生產(chǎn)者按tenant_id的哈希值對主題進(jìn)行分區(qū)咐刨。

[5] 定制數(shù)據(jù)分發(fā)

Druid還通過提供可配置的數(shù)據(jù)分發(fā)方式來支持多租戶∥荼耄可以將Druid的Historical過程配置為層所宰,并可以設(shè)置規(guī)則來確定哪些段進(jìn)入哪個層。一種使用情況是畜挥,與較舊的數(shù)據(jù)相比,最近的數(shù)據(jù)傾向于更頻繁地訪問婴谱。通過分層蟹但,可以將更多的最新細(xì)分托管在功能更強(qiáng)大的硬件上,以提高性能谭羔』牵可以在較便宜的硬件(不同層)上復(fù)制最近段的第二個副本,也可以將較舊的段存儲在此層上瘟裸。

[6] 支持高查詢并發(fā)

Druid的基本計算單位是 段客叉。進(jìn)程并行掃描段,并且可以設(shè)置進(jìn)程數(shù)量Druid.processing.numThreads并行掃描话告。為了并行處理更多數(shù)據(jù)并提高性能兼搏,可以將更多CPU添加到群集中。Druid段的大小應(yīng)確定為使得任何給定段上的任何計算最多應(yīng)在500毫秒內(nèi)完成沙郭。

Druid在內(nèi)部將掃描段的請求存儲在優(yōu)先級隊列中佛呻。如果給定的查詢需要掃描的段數(shù)比集群中可用處理器的總數(shù)更多,并且同時運(yùn)行著許多同樣耗時的查詢病线,則我們不希望任何查詢都被餓死吓著。Druid的內(nèi)部處理邏輯將從一個查詢中掃描一組段,并在掃描完成后立即釋放資源送挑。這允許掃描來自另一個查詢的第二組細(xì)分绑莺。通過使段計算時間保持很小,我們可以確保不斷產(chǎn)生資源惕耕,并且處理與不同查詢有關(guān)的段纺裁。

Druid查詢可以選擇priority在查詢上下文中設(shè)置標(biāo)志∩耐唬可以將低速查詢(下載或報表查詢)降低優(yōu)先級对扶,而更具交互性的查詢可以具有更高的優(yōu)先級。

broker程序也可以專用于給定的層惭缰。例如浪南,一組broker程序可以專用于快速的交互式查詢,而另一組broker程序可以專用于較慢的報告查詢漱受。Druid還提供了一個Router 進(jìn)程络凿,可以根據(jù)各種查詢參數(shù)(數(shù)據(jù)源骡送,時間間隔等)將查詢路由到不同的Broker。

十四絮记、緩存查詢(Query caching)

Druid在段和整個查詢結(jié)果級別都支持查詢結(jié)果緩存摔踱。緩存數(shù)據(jù)可以存儲在本地JVM堆中,也可以存儲在外部分布式鍵/值存儲中怨愤。在所有情況下派敷,Druid緩存都是查詢結(jié)果緩存。唯一的區(qū)別是結(jié)果是特定段的部分結(jié)果還是整個查詢的結(jié)果撰洗。在這兩種情況下篮愉,只要任何基礎(chǔ)數(shù)據(jù)發(fā)生更改,高速緩存都會失效差导;它永遠(yuǎn)不會返回過時的結(jié)果试躏。

段級別的緩存允許利用緩存,即使某些基礎(chǔ)段是可變的并且正在進(jìn)行實時提取设褐。在這種情況下颠蕴,Druid可能會緩存不可變歷史段的查詢結(jié)果,同時在每個查詢上重新計算實時段的結(jié)果助析。在這種情況下犀被,整個查詢結(jié)果級別的緩存沒有用,因為它會不斷地失效貌笨。

段級緩存確實需要Druid合并每個查詢的每個段結(jié)果弱判,即使它們是從緩存中提供的。因此锥惋,如果不存在由于實時提取而導(dǎo)致的無效問題昌腰,則整個查詢結(jié)果級別的緩存會更加高效。

[1] 使用和設(shè)置緩存

所有緩存都有一對參數(shù)膀跌,它們控制著各個查詢?nèi)绾闻c緩存交互遭商,例如“使用”緩存參數(shù)和“填充”緩存參數(shù)。這些設(shè)置必須通過運(yùn)行時屬性在服務(wù)級別啟用捅伤,以利用緩存劫流,但是可以通過在查詢上下文中進(jìn)行設(shè)置來在每個查詢的基礎(chǔ)上進(jìn)行控制〈砸洌“ use”參數(shù)顯然控制查詢是否將使用緩存的結(jié)果祠汇。“populate”參數(shù)控制查詢是否將更新緩存的結(jié)果熄诡。這些是單獨(dú)的參數(shù)可很,以允許對不常見數(shù)據(jù)的查詢使用緩存的結(jié)果,而不會以其他查詢(例如大報表或非常舊的數(shù)據(jù))不太可能重復(fù)使用的結(jié)果污染緩存凰浮。

[2] broker上的查詢緩存

broker同時支持段級緩存和整個查詢結(jié)果級緩存我抠。段級緩存由useCache和populateCache參數(shù)控制苇本。整個查詢結(jié)果級別的緩存由參數(shù) useResultLevelCache和populateResultLevelCache和運(yùn)行時屬性控制 Druid.broker.cache.*。

與在小型集群的“歷史記錄”上啟用查詢緩存相比菜拓,在Broker上啟用段級緩存可以產(chǎn)生更快的結(jié)果瓣窄。對于較小的生產(chǎn)集群(<5個服務(wù)器),這是推薦的設(shè)置纳鼎。設(shè)置在broker上的段級高速緩存是不推薦用于大型生產(chǎn)集群的俺夕,由于當(dāng)屬性Druid.broker.cache.populateCache被設(shè)置為true(和查詢上下文參數(shù)populateCache不設(shè)置為false),從Historicals查詢每個段的基礎(chǔ)上返回結(jié)果贱鄙,Historicals不會能夠進(jìn)行任何本地結(jié)果合并啥么。這降低了Druid集群的伸縮能力。

[3] 查詢Historicals緩存

歷史記錄僅支持段級緩存贰逾。段級緩存由查詢上下文參數(shù)useCache和populateCache和運(yùn)行時屬性控制 Druid.historical.cache.*。

較大的生產(chǎn)集群應(yīng)僅在歷史記錄上啟用段級緩存設(shè)置(而不在Brokers上啟用)菠秒,以避免必須使用Brokers合并所有查詢結(jié)果疙剑。在“Historicals”而不是“Brokers”上啟用緩存填充,可使“歷史記錄”進(jìn)行自己的本地結(jié)果合并践叠,從而減輕了“Brokers”的負(fù)擔(dān)言缤。

[4] 任務(wù)攝取的緩存

任務(wù)執(zhí)行程序進(jìn)程(例如Peon或?qū)嶒炐訧ndexer)僅支持段級緩存。段級緩存由查詢上下文參數(shù)useCache和populateCache 和運(yùn)行時屬性控制 Druid.realtime.cache.*禁灼。

較大的生產(chǎn)集群應(yīng)僅在任務(wù)執(zhí)行流程上啟用段級緩存填充(而不在Broker上啟用)管挟,以避免必須使用Brokers合并所有查詢結(jié)果。在“Historicals”而不是“Brokers”上啟用緩存填充弄捕,可使“歷史記錄”進(jìn)行自己的本地結(jié)果合并僻孝,從而減輕了“Brokers”的負(fù)擔(dān)。

請注意守谓,任務(wù)執(zhí)行器進(jìn)程僅支持將其數(shù)據(jù)保留在本地的caffeine緩存穿铆,例如緩存。之所以存在此限制斋荞,是因為緩存將結(jié)果存儲在攝取任務(wù)所生成的中間部分片段的級別上荞雏。這些中間部分段在各個任務(wù)副本之間不一定是相同的,因此遠(yuǎn)程高速緩存類型 例如memcached平酿,任務(wù)執(zhí)行程序進(jìn)程將忽略它們凤优。

十五、過濾查詢(Spatial filters)

Druid支持根據(jù)原點(diǎn)和界限來過濾空間索引蜈彼。

在任何數(shù)據(jù)規(guī)范中筑辨,都可以選擇提供空間維度。例如柳刮,對于JSON數(shù)據(jù)規(guī)范挖垛,可以如下指定空間尺寸:

{
    "type": "hadoop",
    "dataSchema": {
        "dataSource": "DatasourceName",
        "parser": {
            "type": "string",
            "parseSpec": {
                "format": "json",
                "timestampSpec": {
                    "column": "timestamp",
                    "format": "auto"
                },
                "dimensionsSpec": {
                    "dimensions": [],
                    "spatialDimensions": [{
                        "dimName": "coordinates",
                        "dims": ["lat", "long"]
                    }]
                }
            }
        }
    }
}

空間過濾器

屬性 描述 必要
dimName 空間維度名稱痒钝。空間維度可以由多個其他維度構(gòu)成痢毒,也可以作為事件的一部分存在送矩。如果空間維度已經(jīng)存在,則它必須是一個坐標(biāo)值數(shù)組哪替。
dims 組成空間維度的維度名稱列表栋荸。

空間過濾器語法

"filter" : {
    "type": "spatial",
    "dimension": "spatialDim",
    "bound": {
        "type": "rectangular",
        "minCoords": [10.0, 20.0],
        "maxCoords": [30.0, 40.0]
    }
}

綁定類型

  • rectangular

    屬性 描述 必要
    minCoords 坐標(biāo)[x,y凭舶,z晌块,…]的最小尺寸坐標(biāo)列表
    maxCoords 坐標(biāo)[x,y帅霜,z匆背,…]的最大尺寸坐標(biāo)列表
  • radius

    屬性 描述 必要
    座標(biāo) 原點(diǎn)坐標(biāo)形式為[x,y身冀,z钝尸,…]
    半徑 浮點(diǎn)半徑值
  • polygon

    屬性 描述 必要
    橫坐標(biāo) 多邊形角的水平坐標(biāo)
    縱坐標(biāo) 多邊形角的垂直坐標(biāo)
?著作權(quán)歸作者所有,轉(zhuǎn)載或內(nèi)容合作請聯(lián)系作者
  • 序言:七十年代末,一起剝皮案震驚了整個濱河市搂根,隨后出現(xiàn)的幾起案子珍促,更是在濱河造成了極大的恐慌,老刑警劉巖剩愧,帶你破解...
    沈念sama閱讀 212,383評論 6 493
  • 序言:濱河連續(xù)發(fā)生了三起死亡事件猪叙,死亡現(xiàn)場離奇詭異联逻,居然都是意外死亡从祝,警方通過查閱死者的電腦和手機(jī),發(fā)現(xiàn)死者居然都...
    沈念sama閱讀 90,522評論 3 385
  • 文/潘曉璐 我一進(jìn)店門荸哟,熙熙樓的掌柜王于貴愁眉苦臉地迎上來五督,“玉大人藏否,你說我怎么就攤上這事〕浒” “怎么了副签?”我有些...
    開封第一講書人閱讀 157,852評論 0 348
  • 文/不壞的土叔 我叫張陵,是天一觀的道長基矮。 經(jīng)常有香客問我淆储,道長,這世上最難降的妖魔是什么家浇? 我笑而不...
    開封第一講書人閱讀 56,621評論 1 284
  • 正文 為了忘掉前任本砰,我火速辦了婚禮,結(jié)果婚禮上钢悲,老公的妹妹穿的比我還像新娘点额。我一直安慰自己舔株,他們只是感情好,可當(dāng)我...
    茶點(diǎn)故事閱讀 65,741評論 6 386
  • 文/花漫 我一把揭開白布还棱。 她就那樣靜靜地躺著载慈,像睡著了一般。 火紅的嫁衣襯著肌膚如雪珍手。 梳的紋絲不亂的頭發(fā)上办铡,一...
    開封第一講書人閱讀 49,929評論 1 290
  • 那天,我揣著相機(jī)與錄音琳要,去河邊找鬼寡具。 笑死,一個胖子當(dāng)著我的面吹牛稚补,可吹牛的內(nèi)容都是我干的童叠。 我是一名探鬼主播,決...
    沈念sama閱讀 39,076評論 3 410
  • 文/蒼蘭香墨 我猛地睜開眼课幕,長吁一口氣:“原來是場噩夢啊……” “哼拯钻!你這毒婦竟也來了?” 一聲冷哼從身側(cè)響起撰豺,我...
    開封第一講書人閱讀 37,803評論 0 268
  • 序言:老撾萬榮一對情侶失蹤,失蹤者是張志新(化名)和其女友劉穎拼余,沒想到半個月后污桦,有當(dāng)?shù)厝嗽跇淞掷锇l(fā)現(xiàn)了一具尸體,經(jīng)...
    沈念sama閱讀 44,265評論 1 303
  • 正文 獨(dú)居荒郊野嶺守林人離奇死亡匙监,尸身上長有42處帶血的膿包…… 初始之章·張勛 以下內(nèi)容為張勛視角 年9月15日...
    茶點(diǎn)故事閱讀 36,582評論 2 327
  • 正文 我和宋清朗相戀三年凡橱,在試婚紗的時候發(fā)現(xiàn)自己被綠了。 大學(xué)時的朋友給我發(fā)了我未婚夫和他白月光在一起吃飯的照片亭姥。...
    茶點(diǎn)故事閱讀 38,716評論 1 341
  • 序言:一個原本活蹦亂跳的男人離奇死亡稼钩,死狀恐怖,靈堂內(nèi)的尸體忽然破棺而出达罗,到底是詐尸還是另有隱情坝撑,我是刑警寧澤,帶...
    沈念sama閱讀 34,395評論 4 333
  • 正文 年R本政府宣布粮揉,位于F島的核電站巡李,受9級特大地震影響,放射性物質(zhì)發(fā)生泄漏扶认。R本人自食惡果不足惜侨拦,卻給世界環(huán)境...
    茶點(diǎn)故事閱讀 40,039評論 3 316
  • 文/蒙蒙 一、第九天 我趴在偏房一處隱蔽的房頂上張望辐宾。 院中可真熱鬧狱从,春花似錦膨蛮、人聲如沸。這莊子的主人今日做“春日...
    開封第一講書人閱讀 30,798評論 0 21
  • 文/蒼蘭香墨 我抬頭看了看天上的太陽。三九已至训貌,卻和暖如春制肮,著一層夾襖步出監(jiān)牢的瞬間,已是汗流浹背递沪。 一陣腳步聲響...
    開封第一講書人閱讀 32,027評論 1 266
  • 我被黑心中介騙來泰國打工豺鼻, 沒想到剛下飛機(jī)就差點(diǎn)兒被人妖公主榨干…… 1. 我叫王不留,地道東北人款慨。 一個月前我還...
    沈念sama閱讀 46,488評論 2 361
  • 正文 我出身青樓儒飒,卻偏偏與公主長得像,于是被迫代替她去往敵國和親檩奠。 傳聞我的和親對象是個殘疾皇子桩了,可洞房花燭夜當(dāng)晚...
    茶點(diǎn)故事閱讀 43,612評論 2 350

推薦閱讀更多精彩內(nèi)容