【发布时间】:2017-05-04 18:38:22
【问题描述】:
第一篇文章:SOLR
我和我的团队在使用 Solr 时遇到了问题,我们未能找到解决方案,但我们对此进行了很多思考。所以我们决定在这里问。
有问题:非常快速地读取和更新具有数百万(甚至更多)子元素关系的元素之间的关系。 p>
目前我们有这样的结构:
ELEMENT
{
id: 1,
name : element1
},
{
id: 2,
name : element2
},
[...]
{
id: 10000,
name : element10000
}
SUBELEMENT
{
id: 1,
ids_elements : 1117|165|27|32|4577
name : subelement1
},
{
id: 2,
ids_elements : 1117|416|278
name : subelement2
},
[...]
{
id: 15000000,
ids_elements : 1117|2428|3457|5475|32|958
name : subelement15000000
}
(我使用大ID是因为它符合我们的需求)
通过这个方法,我们可以很容易的得到每个子元素属于一个元素(非常快,比如10-20毫秒就可以得到100000个子-元素)。 但是,以上面的示例为例,删除每个 子元素上的 元素“1117”,更新时间太长(如 10 秒更新 100000 次)。
我想要这样的结构:
ELEMENT
{
id: 1,
name : element1,
ids_subelements : 1|2|3|...12458765|12458766... (few millions)
},
{
id: 2,
name : element2
ids_subelements : 1|2|3|...12458765|12458766... (few other millions)
},
[...]
{
id: 10000,
name : element10000
ids_subelements : 1|2|3|...12458765|12458766... (few other millions)
}
但我们超出了 Solr 的限制。
以前有人解决过这个问题吗?或者有一个想法来获得 Solr 的正确数据结构?
Solr 是这种交互的最佳解决方案吗?
感谢您的宝贵时间!
更新 1:SQL
它已经在 Solr 中非规范化了。在 Sql 规范化数据库中,我们有这样的东西(我解释它是为了更好地理解问题):
ELEMENT(id_element, name)
ELEMENT_OWN_SUBELEMENT(id_element, id_subelement)
SUBELEMENT(id_subelement, name_subelement)
所以在 Sql 中我们需要这样更新数据:
DELETE FROM element_own_subelement
WHERE id_element = :id_element
AND id_subelement = :id_subelement;
-- (one row concerned);
DELETE FROM element_own_subelement
WHERE id_element = :id_element;
-- (potentially there are millions data concerned)
DELETE FROM element_own_subelement
WHERE id_subelement = :id_subelement;
-- potentially there are thousands data concerned)
插入Sql 请求也是一样。我们需要在几秒钟内在 element_own_subelement 中插入数百万条数据。
我们求助于 Solr 来解决阅读问题。它做到了!但是我们没有解决插入/更新性能问题。
更新 2:具体案例
我试图用一个具体的案例来解释我们的问题:
SQL:
-- Main data
POINT_OF_INTEREST (id_poi, name, [...])
-- Datasets & filtering
DATASET(id_dataset, name, [...])
DATASET_OWN_POINT_OF_INTEREST(id_dataset, id_poi)
FILTERING(id_filtering, id_dataset)
-- Data displaying
MODULE (id_module, name, [...])
MODULE_OWN_POINT_OF_INTEREST(id_module, id_poi)
所以:
- 我们将数据分组到数据集中
- 我们将数据集与模块相关联
- 可以为模块过滤数据集
- 我们根据过滤后的数据集定义模块的显示数据 => 只是此时我们将文档插入到 SOLR 核心中。
我们的 SOLR 核心文档示例:
SOLR core "POINT_OF_INTEREST":
{
id_poi : 13,
ids_modules : 1|5|8|7|24, /* Results of the filtering */
name : "POI thirteen",
ids_datasets : 25|5|7
}
要从模块“24”获取数据,我必须像这样请求“point_of_interest”核心:ids_modules:24。真的很快。
但是,如果我保存一个新的过滤,我必须在我的 SOLR 核心中执行这些操作:
- 删除“ids_modules”字段中与所有不在过滤数据结果中的文档相关的数字“24”
- 在与过滤数据结果中的所有文档相关的字段“ids_modules”中添加数字“24”。 考虑到我们每天可能有 1 / 2 百万数据要更新多次,此操作非常缓慢。
我想解决这两个问题:
- 如果我可以用 SOLR 比 SQL 更快地完成复杂的过滤操作
- 如果有一种方法可以让我的数据系统正常工作,而无需系统地对 SOLR 核心进行数十万次更新
更新 3:来自 SOLR 数据库的示例
{
"votes_moins": "",
"id_module": "957654|1445047|1485752|1445843|1854865|1491371|1445993|1478994|1965107|1755131|1725201|1785227|1564235|1585245|1545261|1255272|1542273|1585349|1545434|1585444|1115583|1225671|1585672|1588712|1545730|1775826|1596666|1555988|1675344|1256417|16456683|1856983|1757004|12571566|1715593|1457200|1757218|1777428|172455|1845053|1058425|108594|1885677|1748751|14874647|184817|1955120|1569536|1945635|1259825|2120353|2075726|2850779|2221051|2121129|2421264|2331600|28561607|27771611|2562107|2782553|2225916|2663224|2653225|2235717|2442252|249491|2251440|265069|2365104|2687789|275048|4270620|275092|270278|65273947|257425|274451|7275509|2275811|272605|4527690|279721|2277630|2754808|278038|5280652|2080935|280599|2481710|8281161|328211145|2815958|285219|22823435|2686666|2885978|289807|294024|729044|2292156|2892216|2902128|1029256|2932089|2954401|290488|289934|306105|304509|307616|380725|3907598|3208855|3059794|3310714|311079|3151060|315536|351598",
"adresse.altitude": 0,
"id_objet": "1886416_0",
"id_flux": "101|11158|32548|10365460|104686456|1024537|1024568|1054686|1844859|1986559",
"adresse.ville": "Varangéville",
"id_categories": "",
"type": 5,
"difficulte": "16|17",
"id_circuit": "124785_0",
"utilisateur": "u47852;PPDA Tourisme",
"id_sous_categories": "",
"publication_cirkwi": 1,
"description_fr_FR": "Le Lorem Ipsum est simplement du faux texte employé dans la composition et la mise en page avant impression. Le Lorem Ipsum est le faux texte standard de l'imprimerie depuis les années 1500, quand un peintre anonyme assembla ensemble des morceaux de texte pour réaliser un livre spécimen de polices de texte. Il n'a pas fait que survivre cinq siècles, mais s'est aussi adapté à la bureautique informatique, sans que son contenu n'en soit modifié. Il a été popularisé dans les années 1960 grâce à la vente de feuilles Letraset contenant des passages du Lorem Ipsum, et, plus récemment, par son inclusion dans des applications de mise en page de texte, comme Aldus PageMaker.",
"date_creation": 1478509817,
"date_modification": 1473033625,
"adresse.cp": "87456",
"adresse.rue": "",
"langue": "fr_FR",
"id_locomotions": "13|48|74|18",
"adresse.numero_rue": "",
"votes_plus": "7852",
"distance": 189654,
"publication_reseau": 1,
"pseudo_utilisateur": "PPDA1",
"id_utilisateur_auteur": "u47852",
"publication_prive": 0,
"latlng": "49.1234,7.1234",
"geo": [
"49.1234,7.1234"
],
"url_image": "[...]/mypicture.jpg",
"stats_consultation": 20568,
"titre_fr_FR": "Example",
"titre_fr_FR_tri": "Example",
"_version_": "155642045896312192"
}
(值是假的)
性能最差的键是“id_module”和“id_flux”。 data-config.xml中的字段声明
<field column="id_module" name="id_module" />
<field column="id_flux" name="id_flux" />
myschema.xml 中的字段声明
<field name="id_module" type="splitPipeTexte" indexed="true" />
<field name="id_flux" type="splitPipeTexte" indexed="true" />
“splitPipeTexte”声明如下:
<fieldType name="splitPipeTexte" class="solr.TextField">
<analyzer>
<tokenizer class="solr.PatternTokenizerFactory" pattern="\|"/>
</analyzer>
</fieldType>
我知道这是一个复杂的问题。在我的帖子中,我搜索了一些关于这个数据系统的思考,或者对概念错误做出反应。不一定是完整的解决方案。
谢谢!
【问题讨论】:
-
您可以进行一些映射,请参阅:wiki.apache.org/solr/DataImportHandler 但是,我不确定这就是您所追求的。您能否澄清它是基础索引结构、要索引的实际数据结构还是要重新构建索引的数据视图。谢谢
-
这看起来更像是一个经典的数据库作业,而不是 Solr 作业。您似乎没有任何文本搜索功能,那么您希望通过使用 Solr 来完成什么?
-
@LeftyGBalogh :主要问题是在 SOLR 中更新 100000 个文档的时间。我们需要另一种观点,也许这就是我们需要改变的数据结构。这就像对 Mongo link 的“一对多”/“一对多”/“一对多”的解释。
标签: solr database-performance bigdata database nosql