有这样一个需求,在做solr索引优化的设计方案中,业务方给出了一个业务场景,相关的业务表有n多张,需要出一个方案来解决数据库上复杂SQL查询导致的高延时问题,另外顺带通过Solr还需要对一些字段做拼音查询。
利用Solr的倒排索引对数据库的复杂查询是非常奏效的,另外,可以在Solr上事先将数据库中的几张业务表打成宽表的方式,进一步提高查询效率。打宽表是一种常用的优化手段,但是,子业务逻辑表不能太多,太多的话,会造成索引更新维护非常麻烦(如果索引不需要更新的话,那么聚合的子表再多也没有问题),按照笔者的经验,宽表的子表数不能超过5张为宜。
需求分析时,让业务方给出了一份在查询数据库上的一些复杂SQL,大都是有left outer join 的SQl,而且关联的表还不止一个。算了一下,关联到的表有14个,当然不能将这14个表聚合成一个宽表,需要分而治之,将这一堆表切分成相对小的宽表(每个宽表一个solr的collection),这样维护起来相对方便一些。
首先,拿到了以下一份表之间的查询关联关系:
"kind_menu_addition kind_menu menu" "kind_menu_addition kind_menu" "menu_make make menu" "kind_menu menu" "menu kind_menu menu_spec_detail menu_make" "menu kind_menu menu_prop" "menu_make make" "menu_spec_detail spec_detail" "menu_time_price menu kind_menu" "menu_spec_detail spec_detail menu" "suit_menu_detail menu" "suit_menu_change suit_menu_detail menu spec_detail" "suit_menu_detail menu" "kind_menu menu_kind_taste" "menu_kind_taste kind_taste" "menu_kind_taste kind_taste taste" "menu_kind_taste taste"
如上,引号之间描述的是,表之间的关联关系,需要有一个算法,将以上的关联描述关系,计算出有关联关系的表簇。类似,A和B有关联关系,A和C也是有关联关系,那么计算结果应该要得到 A,B,C是一个关联簇。
另外需要说明的是,上面描述关系中menu,kind_menu两个表的出现频率非常高。其实menu表是ER关系的主表,所以需要在计算过程中需要将类似于这样的出现频率高的主表过滤掉。
下面给出具体的算法:
import org.apache.commons.io.FileUtils; import org.apache.commons.io.LineIterator; import org.apache.commons.lang.StringUtils; public class TabClusterStatis { private static Set<String> mainTables = new HashSet<String>(); static { // 主表 mainTables.add("menu"); mainTables.add("kind_menu"); } /** * @param args */ public static void main(String[] args) throws Exception { // 记录每个表和其他表的应用关系 Map<String, TableLink> tabcluster = new HashMap<String, TableLink>(); LineIterator it = FileUtils.lineIterator(new File("D:\\tmp\\tab.txt")); // 计算表之间的引用关系 String tab = null; Set<String> tables = null; TableLink tlink = null; while (it.hasNext()) { tab = it.nextLine(); if (StringUtils.startsWith(tab, "\"")) { tables = new HashSet<String>(); tab = StringUtils.substringAfter(tab, "\""); } boolean endWithSlash = false; if (endWithSlash = StringUtils.endsWith(tab, "\"")) { tab = StringUtils.substringBefore(tab, "\""); } tables.add(tab); if (endWithSlash) { for (String t : tables) { tlink = tabcluster.get(t); if (tlink == null) { tlink = new TableLink(t); tabcluster.put(t, tlink); } tlink.refs.addAll(tables); } } } // 将主表删除不参与计算 Iterator<String> nameIt = tabcluster.keySet().iterator(); while (nameIt.hasNext()) { if (mainTables.contains(nameIt.next())) { nameIt.remove(); } } List<TableLink> tablelist = new ArrayList<TableLink>( tabcluster.values()); TableLink tref1 = null; TableLink tref2 = null; Set<String> subsetTable = null; List<Set<String>> subsetList = new ArrayList<Set<String>>(); for (int i = 0; i < tablelist.size(); i++) { tref1 = tablelist.get(i); if (tref1.hasSetsubWithOther) { continue; } subsetTable = new HashSet<String>(); // subsetTable.add(String.valueOf(i)); subsetTable.addAll(tref1.refs); subsetList.add(subsetTable); for (int j = (i + 1); j < tablelist.size(); j++) { tref2 = tablelist.get(j); if (tref2.hasSetsubWithOther) { continue; } if (tref2.hasSubSet(subsetTable)) { // subsetTable.add("j:" + String.valueOf(j)); subsetTable.addAll(tref2.refs); tref2.hasSetsubWithOther = true; } } for (int jj = tablelist.size() - 1; jj >= (i + 1); jj--) { tref2 = tablelist.get(jj); if (tref2.hasSetsubWithOther) { continue; } if (tref2.hasSubSet(subsetTable)) { // subsetTable.add("jj:" + String.valueOf(jj)); subsetTable.addAll(tref2.refs); tref2.hasSetsubWithOther = true; } } } List<String> sortTables = null; for (Set<String> c : subsetList) { sortTables = new ArrayList<>(c); Collections.sort(sortTables); for (String t : sortTables) { // if (mainTables.contains(t)) { // continue; // } System.out.print(t + ","); } System.out.println(); } } private static class TableLink { private final String name; private final Set<String> refs = new HashSet<String>(); boolean hasSetsubWithOther = false; public TableLink(String name) { super(); this.name = name; } boolean hasSubSet(TableLink refs) { return hasSubSet(refs.refs); } public boolean hasSubSet(Set<String> refs) { for (String tab : refs) { if (mainTables.contains(tab)) { continue; } if (this.refs.contains(tab)) { return true; } } return false; } } }
执行之后会打印如下信息:
kind_menu,kind_taste,menu_kind_taste,taste, kind_menu,menu,menu_time_price, kind_menu,make,menu,menu_make,menu_spec_detail,spec_detail,suit_menu_change,suit_menu_detail, kind_menu,kind_menu_addition,menu, kind_menu,menu,menu_prop,
很好,自动将两两描述信息计算出了5个子表簇,现在我们就可以在solr上集群中构建5个collection。
很显然,这样的做的好处是快不会错,以前都是拍脑袋跟着感觉走,推而广之,在其他场景下也能用上这个算法。
相关推荐
压缩算法 集合 java
进一步压缩代表点集合,在坐标系中拟合代表点即拟合楼梯,通过拟合结果构造多域光网络的全连通图,运用获取的星形拓扑实施多域光网络拓扑聚合,实现多域光网络拓扑聚合算法的设计。为了验证算法的相对失真性能设计...
该算法在改进的HSV颜色空间计算边缘梯度,通过定义的基元模板扫描梯度图像,生成梯度基元图像,将基元和非基元像素分别组合成聚合和非聚合像素集合;最后利用颜色自相关图算法对上述两个集合提取特征矢量,实现了...
17.1 聚合分析 17.2 核算法 17.3 势能法 17.4 动态表 17.4.1 表扩张 17.4.2 表扩张和收缩 思考题 本章注记 第五部分 高级数据结构 第18章 B树 18.1 B树的定义 18.2 B树上的基本操作 ...
与V1.0版相比增加/修正了以下功能! 1.修正了搜索页顶部无广告时的搜索框错位! 2.后台增加了SEO外链工具链接! 3.后台增加了LOGO图片更换功能! 4.册除了网页标题上作者的版权信息,同时首页底部版权信息移至...
为了解决正则化参数确定的问题,进一步提出了聚合(R-CSP-A)的R-CSP,并将一些R-CSP聚合在一起,给出了一个基于集合的解决方案。提出了一种基于BCI竞争三种竞争算法的数据集IVa的算法。实验表明,在SSS(小样本环境)...
主干子图是一些度相对较高节点的集合;而子树则正好相反,幂律特征有效地保证了节点度分布的非均一特性。基于主干子图理论的图聚类算法可以分成两个步骤,即主干子图生成算法和桩树生成算法。主干子图Gs(Vs,Es)与...
计算社会选择的计算机科学领域中的排名聚合算法 什么是新的 已在Python软件包索引(PyPI)上发布,供pip公开下载和安装(请参见下面的安装) 实验和测试已从存储库中排除(现在位于) Plackett-Luce模型混合的矩量...
该算法通过集合聚合度的概念,在图像的颜色统计信息中融人了多粒度的空间聚合信息,具有对图像平移、旋转与尺度变化不敏感及检索性能受数据库大小变化影响较少等特点。为了验证算法的有效性,对该算法进行了性能比较...
在阶段1,如果利用预构建的随机样本RS不能返回满足用户要求的近似结果,那么在阶段2,PAA算法从与查询区域相交的空间区域对应的分片集合IPS中获得更多的随机元组.PAA算法的特色在于:1)如何在不知道IPS包含的每个分片...
和硕沟搜索引擎算法,不需要任何集合,只需放入关键词即可 具有它绝对是一款超级强大的霸屏搜狗泛站点群程序源代码。 这套源代码在某网站上售价1.2万元: 这组网站组的源代码是一个模仿聚合搜索并针对搜狗搜索的程序...
第一步,设所有发送或者接收到的数据为集合 M,将其转换为 json 格式字符串 jsonString(注意:不要转义网址与中文等特殊字符) 第二步,字符串拼接
python中符号集合近似的实现。 基于论文时间序列的符号表示,对流算法有影响 一般使用: from saxpy import SAX s = SAX(wordSize, alphabetSize, epsilon) 您可以选择指定字号,字母大小和epsilon 如果要比较x1...
该算法首先根据CQI(channel quality indicator,信道质量指示)确定CCE(control channel element,控制信道粒子)聚合等级,并进行资源分配,计算可能的聚合等级集合,在首次不成功的情况下,在可能的聚合等级集合...
本文针对多目标分类巾线性聚合模式存在的问题,提出了一种基于贴近度分析的 多目标分类新算法。...它们与评价等级集合中各评价等级的具占近程度,来进行多目标聚合与分类。本文的算例说明了该 算法的可行性。
数组(Array):数组是一种聚合数据类型,它是将具有相同类型的若干变量有序地组织在一起的集合。 链表(Linked List):链表是一种数据元素按照链式存储结构进行存储的数据结构,这种存储结构具有在物理上存在非...
字节跳动java笔算法试题 初创企业 程序员应该访问的最佳网站 一些对程序员有用的网站。 在学习 CS 时,您必须了解一些有用的网站,以便随时了解最新信息,以便更好地掌握技术并学习新事物。 这是您应该访问的一些...
主要内容包括SQL的基础理论、查询优化、查询算法及复杂度,以及在使用子查询、表表达式、排名函数、数据聚合和透视转换、TOP和APPLY、数据修改、分区表、特殊数据结构等实际应用时会遇到的各种高级查询问题和解决...
提取舰船目标的聚合通道特征,并通过聚合通道特征构建的样本训练库和AdaBoost算法完成分类器的训练,利用训练完成后的分类器完成舰船目标的最终判别确认。实验结果表明该算法相较于传统的HOG特征和Haar特征,检测效果...
主要内容包括SQL的基础理论、查询优化、查询算法及复杂度,以及在使用子查询、表表达式、排名函数、数据聚合和透视转换、TOP和APPLY、数据修改、分区表、特殊数据结构等实际应用时会遇到的各种高级查询问题和解决...