Solr如何使用并行SQL接口

2018-12-06 14:35 更新

Solr的并行SQL接口將SQL的強大功能帶入了SolrCloud。

SQL接口將SQL與Solr的全文搜索功能無縫地結(jié)合在一起。支持MapReduce風(fēng)格和JSON Facet API聚合,這意味著SQL接口可以用來支持高查詢量和高基數(shù)用例。

SQL體系結(jié)構(gòu)

SQL接口允許發(fā)送一個SQL查詢到Solr,并使文檔在響應(yīng)時得到回流。在該覆蓋范圍內(nèi),Solr的SQL接口使用Apache Calcite SQL引擎將SQL查詢轉(zhuǎn)換為以Streaming Expressions實現(xiàn)的物理查詢計劃。

Solr集合和數(shù)據(jù)庫表

在標(biāo)準(zhǔn)SELECT語句中,例如:SELECT <expressions> FROM <table>,表名對應(yīng)于Solr集合名稱。表名不區(qū)分大小寫。

SQL查詢中的列名直接映射到正在查詢的集合的Solr索引中的字段。這些標(biāo)識符區(qū)分大小寫。支持別名,可以在ORDER BY子句中引用。

在有限或無限制的查詢中不支持用于指示所有字段的 * 語法。該score字段只能用于包含LIMIT子句的查詢。

例如,我們可以索引Solr的示例文檔,然后構(gòu)造一個類似如下的 SQL 查詢:

SELECT manu as mfr, price as retail FROM techproducts

我們正在使用的Solr的集合是“techproducts”,我們已經(jīng)要求將“manu”和“price”字段返回,并使用新名稱進(jìn)行別名。雖然這個例子不使用這些別名,但我們可以在此基礎(chǔ)上根據(jù)其中一個或多個字段進(jìn)行ORDER BY。

有關(guān)如何為Solr構(gòu)建SQL查詢的更多信息,請參見下面的“Solr SQL語法”部分。

聚合模式

Solr的SQL功能可以通過兩種方式與聚合(結(jié)果分組)結(jié)合使用:

  • facet:這是默認(rèn)的聚合模式,它使用JSON Facet API或StatsComponent進(jìn)行聚合。在這種情況下,聚合邏輯被推入搜索引擎,只有聚合通過網(wǎng)絡(luò)發(fā)送。這是Solr的正常操作模式。當(dāng)GROUP BY字段的基數(shù)低到中等時,這是很快的。但是,當(dāng)GROUP BY字段中有高基數(shù)字段時,它會中斷。
  • map_reduce:這個實現(xiàn)將元組拖到到工作節(jié)點,并在工作節(jié)點上執(zhí)行聚合。它涉及對整個結(jié)果集進(jìn)行排序和分區(qū)并將其發(fā)送給工作節(jié)點。在這種方法中,元組到達(dá)由GROUP BY字段排序的工作節(jié)點。然后,工作節(jié)點可以一次匯總一個組的匯總。這樣可以實現(xiàn)無限的基數(shù)聚合,但是您需要付出通過網(wǎng)絡(luò)將整個結(jié)果集發(fā)送給工作節(jié)點的代價。

當(dāng)將請求發(fā)送到Solr時,這些模式被定義為aggregationMode。

如上所述,聚合模式之間的選擇取決于您正在使用的字段的基數(shù)。如果您在分組的字段中具有低到中等的基數(shù),那么“facet”聚合模式將為您提供更高的性能,因為只返回最終的組,因此與今天的facet工作方式非常相似。但是,如果在字段中的基數(shù)很高,那么帶有工作節(jié)點的“map_reduce”聚合模式將提供更高性能的選項。

配置

用于SQL接口的請求處理程序被配置為隱式加載,這意味著開始使用此功能幾乎沒有什么要做。

/sql請求處理程序

/sql處理程序是并行SQL接口的前端。所有SQL查詢都發(fā)送到/sql處理程序進(jìn)行處理。該處理程序還在map_reduce模式中運行GROUP BY和SELECT DISTINCT查詢時協(xié)調(diào)分布式MapReduce作業(yè)。默認(rèn)情況下,/sql處理程序?qū)钠渥约旱募现羞x擇工作節(jié)點來處理分布式操作。在此默認(rèn)場景中,/sql處理程序所在的集合充當(dāng)MapReduce查詢的默認(rèn)工作者集合。

默認(rèn)情況下,/sql請求處理程序被配置為隱式處理程序,這意味著它在每個Solr安裝中始終處于啟用狀態(tài),不需要進(jìn)一步的配置。

注意:正如在“最佳實踐”小節(jié)中所述,您可能希望為并行SQL查詢設(shè)置一個單獨的集合。如果您擁有高基數(shù)字段和大量數(shù)據(jù),請務(wù)必查看該部分,并考慮使用單獨的集合。

/stream和/export請求處理程序

Streaming API是SolrCloud的可擴展并行計算框架。流表達(dá)式為Streaming API提供查詢語言和序列化格式。

Streaming API提供對快速MapReduce的支持,允許它在極大的數(shù)據(jù)集上執(zhí)行并行關(guān)系代數(shù)。在覆蓋范圍內(nèi),SQL接口使用Apache Calcite SQL解析器解析SQL查詢。然后將查詢轉(zhuǎn)換為并行查詢計劃。并行查詢計劃使用Streaming API和Streaming Expressions表示。

像/sql請求處理程序中,/stream和/export請求處理程序被配置為隱式的處理程序,并且不需要進(jìn)一步的配置。

字段

在某些情況下,SQL查詢中使用的字段必須配置為DocValue字段。如果查詢是無限的,則所有的字段必須是DocValue字段。如果查詢是有限的(使用該limit子句),則字段不需要啟用DocValues。

發(fā)送查詢

SQL接口提供了一個基本的JDBC驅(qū)動程序和一個HTTP接口來執(zhí)行查詢。

JDBC驅(qū)動程序

使用SolrJ的JDBC驅(qū)動程序。以下是創(chuàng)建連接并使用JDBC驅(qū)動程序執(zhí)行查詢的示例代碼:

Connection con = null;
try {
    con = DriverManager.getConnection("jdbc:solr://" + zkHost + "?collection=collection1&aggregationMode=map_reduce&numWorkers=2");
    stmt = con.createStatement();
    rs = stmt.executeQuery("SELECT a_s, sum(a_f) as sum FROM collection1 GROUP BY a_s ORDER BY sum desc");

    while(rs.next()) {
        String a_s = rs.getString("a_s");
        double s = rs.getDouble("sum");
    }
} finally {
    rs.close();
    stmt.close();
    con.close();
}

連接URL必須包含zkHost和collection參數(shù)。該集合必須是指定ZooKeeper主機上的有效SolrCloud集合。該集合還必須使用/sql處理程序進(jìn)行配置。aggregationMode和numWorkers參數(shù)都是可選的。

HTTP接口

Solr通過/sql處理程序接受并行SQL查詢。

下面是在facet模式下執(zhí)行SQL聚合查詢的curl命令示例:

curl --data-urlencode 'stmt=SELECT to, count(*) FROM collection4 GROUP BY to ORDER BY count(*) desc LIMIT 10' http://localhost:8983/solr/collection4/sql?aggregationMode=facet

以下是樣本結(jié)果集:

{"result-set":{"docs":[
   {"count(*)":9158,"to":"pete.davis@enron.com"},
   {"count(*)":6244,"to":"tana.jones@enron.com"},
   {"count(*)":5874,"to":"jeff.dasovich@enron.com"},
   {"count(*)":5867,"to":"sara.shackleton@enron.com"},
   {"count(*)":5595,"to":"steven.kean@enron.com"},
   {"count(*)":4904,"to":"vkaminski@aol.com"},
   {"count(*)":4622,"to":"mark.taylor@enron.com"},
   {"count(*)":3819,"to":"kay.mann@enron.com"},
   {"count(*)":3678,"to":"richard.shapiro@enron.com"},
   {"count(*)":3653,"to":"kate.symes@enron.com"},
   {"EOF":"true","RESPONSE_TIME":10}]}
}

請注意,結(jié)果集是具有與SQL列列表匹配的鍵/值對的元組數(shù)組。最后的元組包含EOF標(biāo)志,表示流的結(jié)束。

Solr SQL語法

Solr支持廣泛的SQL語法。

SQL解析器對大小寫不敏感:Solr使用SQL解析器來轉(zhuǎn)換SQL語句是不區(qū)分大小寫的。但是,為了便于閱讀,本頁面上的所有示例均使用大寫的關(guān)鍵字。

轉(zhuǎn)義保留字

如果在SQL查詢中使用保留字,則SQL解析器將返回一個錯誤。保留字可以被轉(zhuǎn)義并且包含在查詢中。例如:

select `from` from emails

SELECT語句

Solr支持有限和無限的選擇查詢。除了SQL語句中的LIMIT子句之外,這兩種查詢之間的語法是相同的。但是,它們對數(shù)據(jù)的存儲方式有非常不同的執(zhí)行計劃和不同的要求。下面的部分探討了這兩種類型的查詢。

帶有LIMIT的基本SELECT語句

有限的選擇查詢遵循以下基本語法:

SELECT fieldA as fa, fieldB as fb, fieldC as fc FROM tableA WHERE fieldC = 'term1 term2' ORDER BY fa desc LIMIT 100

我們在這個示例中已經(jīng)介紹了許多語法選項,因此讓我們來看看下面可能出現(xiàn)的情況。

WHERE子句和布爾謂詞

WHERE子句必須在謂詞的一側(cè)有一個字段。兩個常量(5 < 10)或兩個字段(fielda > fieldb)不被支持。子查詢也不受支持。

該WHERE子句允許將Solr的搜索語法注入到SQL查詢中。在這個例子中:

WHERE fieldC = 'term1 term2'

上面的謂詞將對 fieldC 中的短語“term1 term2”執(zhí)行全文搜索。

要執(zhí)行非短語查詢,只需在單引號內(nèi)添加括號。例如:

WHERE fieldC = '(term1 term2)'

上面的謂詞在 fieldC 中搜索 term1 或 term2。
Solr 范圍查詢語法可按如下方式使用:

WHERE fieldC = '[0 TO 100]'

復(fù)雜的布爾查詢可以如下指定:

WHERE ((fieldC = 'term1' AND fieldA = 'term2') OR (fieldB = 'term3'))

要指定NOT查詢,請使用以下AND NOT語法:

WHERE (fieldA = 'term1') AND NOT (fieldB = 'term2')

支持的WHERE運算符

并行SQL接口支持并推送大多數(shù)常見的SQL操作符,具體為:

操作符 描述 示例 Solr查詢

=

等于

fielda = 10

fielda:10

<>

不相等

fielda <> 10

-fielda:10

!=

不相等

fielda != 10

-fielda:10

>

大于

fielda > 10

fielda:{10 TO *]

> =

大于或等于

fielda >= 10

fielda:[10 TO *]

<

小于

fielda < 10

fielda:[* TO 10}

<=

小于或等于

fielda <= 10

fielda:[* TO 10]

一些不支持的運算符是:BETWEEN、LIKE 和 IN。但是,有BETWEEN和LIKE的解決方法。

  • BETWEEN可以用范圍查詢來支持,比如:field = [50 TO 100]。
  • 一個簡單的LIKE可以和通配符一起使用,比如:field = 'sam*'。

ORDER BY子句

該ORDER BY子句直接映射到Solr字段。支持多個ORDER BY字段和方向。

在指定了限制的查詢中,score 字段在ORDER BY子句中被接受。

如果ORDER BY子句包含GROUP BY子句中的確切字段,則對返回的結(jié)果沒有限制。如果ORDER BY子句包含與GROUP BY子句不同的字段,則會自動應(yīng)用100的限制。要增加此限制,您必須在LIMIT子句中指定一個值。

按字段排序區(qū)分大小寫。

LIMIT子句

將結(jié)果集限制為指定的大小。在上面的例子中,該LIMIT 100子句將結(jié)果集限制為100條記錄。

有限和無限查詢之間有一些區(qū)別需要注意:

  • 有限的查詢支持字段列表和ORDER BY中的score。無限制的查詢不支持。
  • 有限的查詢允許在字段列表中存儲任何字段。無限的查詢需要將這些字段存儲為DocValues字段。
  • 有限的查詢允許ORDER BY列表中的任何索引字段。無限的查詢需要將這些字段存儲為DocValues字段。

SELECT DISTINCT查詢

SQL接口支持SELECT DISTINCT查詢的MapReduce和Facet實現(xiàn)。

MapReduce實現(xiàn)將元組混合到執(zhí)行Distinct操作的工作節(jié)點。這個實現(xiàn)可以在極高的基數(shù)字段上執(zhí)行不同的操作。

Facet實現(xiàn)使用JSON Facet API將Distinct操作下推到搜索引擎中。此實現(xiàn)旨在針對低到中等基數(shù)字段的高性能、高QPS情況。

該aggregationMode參數(shù)在JDBC驅(qū)動程序和HTTP接口中均可用于選擇底層實現(xiàn)(map_reduce 或 facet)。這兩個實現(xiàn)的SQL語法是相同的:

SELECT distinct fieldA as fa, fieldB as fb FROM tableA ORDER BY fa desc, fb desc

統(tǒng)計

SQL接口支持在數(shù)字字段上計算簡單的統(tǒng)計信息。支持的函數(shù)是:count(*),min,max,sum和avg。

由于這些函數(shù)從不需要對數(shù)據(jù)進(jìn)行混洗,所以聚合被下推到搜索引擎中,并由StatsComponent生成。

SELECT count(*) as count, sum(fieldB) as sum FROM tableA WHERE fieldC = 'Hello'

GROUP BY聚合

SQL接口也支持GROUP BY聚合查詢。

與SELECT DISTINCT查詢一樣,SQL接口同時支持MapReduce實現(xiàn)和Facet實現(xiàn)。MapReduce實現(xiàn)可以在極高的基數(shù)域上構(gòu)建聚合。Facet實現(xiàn)提供了在基數(shù)適中的字段上的高性能聚合。

基本GROUP BY與聚合

以下是請求聚合的GROUP BY查詢的基本示例:

SELECT fieldA as fa, fieldB as fb, count(*) as count, sum(fieldC) as sum, avg(fieldY) as avg FROM tableA WHERE fieldC = 'term1 term2'
GROUP BY fa, fb HAVING sum > 1000 ORDER BY sum asc LIMIT 100

讓我們把它分解成下面的幾個部分:

列標(biāo)識符和別名

列標(biāo)識符可以包含Solr索引和聚合函數(shù)中的兩個字段。受支持的聚合函數(shù)是:

  • count(*):統(tǒng)計一組 buckets 中的記錄數(shù)。
  • sum(field):對一組 buckets 上的數(shù)值字段求和。
  • avg(field):在一組 buckets 的數(shù)值字段進(jìn)行平均值。
  • min(field):通過一組 buckets 返回數(shù)值字段的最小值。
  • max:(field):返回一個數(shù)字在一組 buckets 上的最大數(shù)值。

字段列表中的非函數(shù)字段決定了計算聚合的字段。

GROUP BY子句最多可以包含Solr索引中的4字段。這些字段應(yīng)該與字段列表中的非函數(shù)字段相對應(yīng)。

HAVING子句

HAVING子句可能包含在字段列表中列出的任何函數(shù)。這樣的復(fù)雜HAVING子句被支持:

SELECT fieldA, fieldB, count(*), sum(fieldC), avg(fieldY)
FROM tableA
WHERE fieldC = 'term1 term2'
GROUP BY fieldA, fieldB
HAVING ((sum(fieldC) > 1000) AND (avg(fieldY) <= 10))
ORDER BY sum(fieldC) asc
LIMIT 100

最佳實踐

單獨的集合

為/sql處理程序創(chuàng)建一個單獨的SolrCloud集合是有意義的。這個集合可以使用SolrCloud的標(biāo)準(zhǔn)集合API創(chuàng)建。

由于此集合僅用于處理/sql請求并提供工作節(jié)點池,因此此集合不需要保存任何數(shù)據(jù)。Worker 節(jié)點是從/sql處理程序集合中的整個可用節(jié)點池中隨機選擇的。所以為了增加這個集合動態(tài)副本可以被添加到現(xiàn)有的分片。新副本將在添加完成后自動啟用。

并行SQL查詢

前面的部分描述了SQL接口如何將SQL語句轉(zhuǎn)換為流表達(dá)式。請求的參數(shù)之一是:aggregationMode,它定義查詢是否應(yīng)該使用類似 MapReduce 的混洗技術(shù)或?qū)⒉僮飨蛳峦迫胨阉饕妗?br>

并行SQL查詢組成

并行SQL體系結(jié)構(gòu)由三個邏輯層組成:一個SQL層,一個工作層和一個數(shù)據(jù)表層。默認(rèn)情況下,SQL和工作層將折疊到相同的物理SolrCloud集合中。

SQL層

SQL層是/sql處理程序所在的位置。該/sql處理程序采用SQL查詢,然后將其轉(zhuǎn)換為并行查詢計劃。然后選擇要執(zhí)行計劃的工作節(jié)點,并將查詢計劃發(fā)送到要并行運行的每個工作節(jié)點。

一旦工作節(jié)點執(zhí)行了查詢計劃,/sql處理程序就會執(zhí)行工作節(jié)點返回的元組的最終合并。

工作層

工作層中的工作從/sql處理程序接收查詢計劃并執(zhí)行并行查詢計劃。并行執(zhí)行計劃包括需要在數(shù)據(jù)表層上進(jìn)行的查詢和滿足查詢所需的關(guān)系代數(shù)。分配給查詢的每個工作節(jié)點都從數(shù)據(jù)表中從元組的 1/N 中被打亂。工作節(jié)點將查詢計劃和流元組執(zhí)行回工作節(jié)點。

數(shù)據(jù)表層

數(shù)據(jù)表層是表所在的位置。每個表都是自己的SolrCloud集合。數(shù)據(jù)表層接收來自工作節(jié)點的查詢并發(fā)出元組(搜索結(jié)果)。數(shù)據(jù)表層也處理發(fā)送給工作層的元組的初始排序和分區(qū)。這意味著元組總是在攻擊網(wǎng)絡(luò)之前進(jìn)行排序和分區(qū)。分區(qū)的元組以正確的排序順序直接發(fā)送到正確的工作節(jié)點,隨時可以減少。

 Solr并行SQL查詢?nèi)绾畏植? class=

上面的圖顯示了三個層次,它們被分成不同的SolrCloud集合的三個層。實際上,/sql處理程序和工作者集合默認(rèn)共享相同的集合。

注意:該圖顯示了單個并行SQL查詢(基于MapReduce的SQL)的網(wǎng)絡(luò)流。此map_reduce聚合模式用于GROUP BY聚合或SELECT DISTINCT查詢時使用此網(wǎng)絡(luò)流。當(dāng)使用facet聚合模式時,使用傳統(tǒng)的SolrCloud網(wǎng)絡(luò)流(不含工作)。

以下是流程的描述:

  1. 客戶端將SQL查詢發(fā)送到/sql處理程序。請求由單個/sql處理程序?qū)嵗幚怼?/li>
  2. 該/sql處理器解析SQL查詢,并創(chuàng)建并行查詢計劃。
  3. 查詢計劃發(fā)送到工作節(jié)點(綠色)。
  4. 工作節(jié)點并行執(zhí)行計劃。該圖顯示了每個聯(lián)系數(shù)據(jù)表層(藍(lán)色)中的集合的工作節(jié)點。
  5. 數(shù)據(jù)表層中的集合是SQL查詢中的表。請注意,該集合有五個分別具有3個副本的分片。
  6. 請注意,每個worker聯(lián)系每個分片的一個副本。因為有5個worker,每個worker從每個碎片返回1/5的搜索結(jié)果。分區(qū)是在數(shù)據(jù)表層中完成的,因此網(wǎng)絡(luò)中沒有數(shù)據(jù)的重復(fù)。
  7. 另外請注意,在這個設(shè)計中,數(shù)據(jù)層中的所有副本都在同時對數(shù)據(jù)進(jìn)行混洗(排序和分區(qū))。隨著碎片,副本和worker數(shù)量的增長,這種設(shè)計可以將大量計算能力應(yīng)用于單個查詢。
  8. 工作節(jié)點并行處理從數(shù)據(jù)表層返回的元組。工作節(jié)點執(zhí)行滿足查詢計劃所需的關(guān)系代數(shù)。
  9. 工作節(jié)點將元組流回到最終合并完成的/sql處理程序中,最后將元組流回到客戶端。

SQL客戶端和數(shù)據(jù)庫可視化工具

SQL接口支持從SQL客戶端和數(shù)據(jù)庫可視化工具(如DbVisualizer和Apache Zeppelin)發(fā)送的查詢。

通用客戶端

對于大多數(shù)基于Java的客戶端,需要將以下jar包放在客戶端類路徑中:

  • 所有.jars在 $SOLR_HOME/dist/solrj-libs 中找到
  • SolrJ .jar 在 $SOLR_HOME/dist/solr-solrj-<version>.jar 被發(fā)現(xiàn)

如果您使用的是Maven,那么這個org.apache.solr.solr-solrj工件包含所需的jar。

一旦jarpath在類路徑中可用,Solr JDBC驅(qū)動程序名稱就是:org.apache.solr.client.solrj.io.sql.DriverImpl,并且可以使用以下連接字符串格式進(jìn)行連接:

jdbc:solr://SOLR_ZK_CONNECTION_STRING?collection=COLLECTION_NAME

還有其他的參數(shù)可以選擇性地添加到連接字符串中,例如aggregationMode和numWorkers。

DBVisualizer

在Solr JDBC - DbVisualizer部分提供了設(shè)置DbVisualizer的分步指南。

SQuirreL SQL

有關(guān)設(shè)置SQuirreL SQL的分步指南,請參見Solr JDBC - SQuirreL SQL。

Apache Zeppelin

有關(guān)設(shè)置Apache Zeppelin的分步指南,請參見Solr JDBC - Apache Zeppelin。

Python/Jython

Solr JDBC - Python / Jython部分提供了使用Python和Jython連接Solr和Solr JDBC驅(qū)動程序的示例。

R

Solr JDBC-R部分提供了使用R連接到Solr和Solr JDBC驅(qū)動程序的示例。


以上內(nèi)容是否對您有幫助:
在線筆記
App下載
App下載

掃描二維碼

下載編程獅App

公眾號
微信公眾號

編程獅公眾號