在Solr上快速阅读或更新数百万个关系

时间:2016-12-19 16:38:50

标签: solr database-performance bigdata database nosql

第一篇文章:SOLR

我和我的团队遇到 Solr 的问题,我们找不到解决方案,但我们对此有很多想法。所以我们决定在这里问。

有问题:在元素之间快速读取和更新关系,只有几百万(甚至更多)子元素关系。

目前我们有这样的结构:

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 Sub-元件)。 但是,以上面的例子为例,删除元素" 1117"在每个子元素上,更新的时间太长(对于100000次更新,则为10秒)。

我想要一个像这样的结构:

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 核心中执行这些操作:

  • 删除号码" 24"在现场" ids_modules"与过滤数据结果中没有的所有文件有关
  • 添加号码" 24"在现场" ids_modules"与过滤数据结果中的所有文档有关。 考虑到我们每天可能有数百万的数据需要多次更新,因此此操作非常缓慢。

我想解决这两个问题:

  • 如果我可以使用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" />

其中&#34; splitPipeTexte&#34;声明如下:

<fieldType name="splitPipeTexte" class="solr.TextField">
    <analyzer>
        <tokenizer class="solr.PatternTokenizerFactory" pattern="\|"/>
    </analyzer>
</fieldType>

我意识到这是一个复杂的问题。在我的帖子中,我搜索了一些关于这个数据系统的反思,或者对概念错误作出反应。不一定是完整的解决方案。

谢谢!

1 个答案:

答案 0 :(得分:1)

你正在从错误的一端看这个问题。您需要在Solr中为搜索整理数据,而不仅仅是尝试映射您的结构。

最有可能的是,你会将你的结构扁平化(非规范化)成平坦的记录。而且,如果你有非常复杂的结构,你可能最终将你的原始信息存储在一个单独的(图?)数据库中,只返回Solr的ID。原始结构越复杂,情况就越有可能。