1、優化查詢精度
優化原因:當維度過多時,查詢很復雜,效率較慢。因此看能否通過優化sql的方式來提高查詢效率。
代碼跟蹤查看(維度多余3時查詢條件里面有in,優化不用in關鍵字)
public abstract class AbstractQuerySpec implements QuerySpec { protected Map<String, String> nonDistinctGenerateSql(SqlQuery sqlQuery){ String expr = column.generateExprString(sqlQuery); StarColumnPredicate predicate = getColumnPredicate(i); final String where = RolapStar.Column.createInExpr( expr, predicate, column.getDatatype(), sqlQuery); if (!where.equals("true")) { sqlQuery.addWhere(where); }
public class Aggregation { createSegments{ new Segment( star, constrainedColumnsBitKey, columns, measure, predicates,//這里 : [true, true, true, F_JCJY_CODE_SSQ.SFDM={230000, 370000}] 當為具體數值不為true時使用了in(230000,370000) Collections.<Segment.ExcludedRegion>emptyList(),compoundPredicateList); }
private StarColumnPredicate[] initPredicates() { StarColumnPredicate[] predicates = new StarColumnPredicate[columns.length]; for (int j = 0; j < columns.length; j++) { Set<StarColumnPredicate> valueSet = valueSets[j]; StarColumnPredicate predicate; if (valueSet == null) { predicate = LiteralStarPredicate.FALSE; } else { ValueColumnPredicate[] values = valueSet.toArray( new ValueColumnPredicate[valueSet.size()]); // Sort array to achieve determinism in generated SQL. Arrays.sort( values, ValueColumnConstraintComparator.instance); predicate = new ListColumnPredicate( columns[j], Arrays.asList((StarColumnPredicate[]) values)); } predicates[j] = predicate; } return predicates; }
AggregationManager.loadAggregation(
cacheMgr,
cellRequestCount,
measuresList,
columns,
batchKey,
predicates,
groupingSetsCollector,
segmentFutures);
predicates = aggregation.optimizePredicates(columns, predicates); public StarColumnPredicate[] optimizePredicates( RolapStar.Column[] columns, StarColumnPredicate[] predicates) {
跟蹤到最后,來到下面的代碼處
if (MondrianProperties.instance().OptimizePredicates.get() || bloats[j] == 1){ newPredicates[j] = new LiteralStarPredicate(columns[j], true);//設置為ture }
第一個條件
MondrianProperties.instance().OptimizePredicates.get() 配置mondrian.properties里面的(默認也是true) mondrian.rolap.aggregates.optimizePredicates=true
第二個條件
bloats[j] == 1 mondrian包里面的Aggregation類的optimizePredicates方法修改如下: if (valueCount < 2) { bloats[i] = 1.0;//原來是0.0 continue; } if (valueCount > maxConstraints) { bloats[i] = 1.0; continue; } 而 maxConstraints 是在 mondrian。properties里面配置的。 默認是:1000,表示如果in里面的值小於1000個時,采用in精細化查詢,否則不帶in查詢語句。這里我們配置為1. mondrian.rolap.maxConstraints=1
總結:需要修改的地方如下:
#Aggregation類 if (valueCount < 2) { bloats[i] = 1.0;//原來是0.0 continue; } #mondrian.properties配置文件 mondrian.rolap.maxConstraints=1 mondrian.rolap.aggregates.optimizePredicates=true
注意:后來發現,查詢效率慢主要是因為查詢出的結果需要經過一系列的矩陣變換計算和遞歸計算,是作為數據的后處理操作。
如果報出內存溢出,請增大應用內存。
2、緩存結果
查詢后將結果緩存,以便第二次查詢時提高查詢效率
配置mondrian.properties
//開啟聚合表功能
mondrian.rolap.aggregates.ChooseByVolume=true
mondrian.rolap.aggregates.Read=true
mondrian.rolap.aggregates.Use=true
//緩存結果集
mondrian.rolap.cellBatchSize=0
mondrian.rolap.star.disableCaching=false
mondrian.expCache.enable=true
mondrian.rolap.EnableRolapCubeMemberCache=true
mondrian.result.highCardChunkSize=50
mondrian.rolap.evaluate.MaxEvalDepth=1
//允許監控內存、顯示維度前綴、空值處理
mondrian.util.memoryMonitor.enable=true
mondrian.olap.elements.NeedDimensionPrefix=true
mondrian.olap.NullMemberRepresentation=\u7a7a
//sql處理
mondrian.rolap.generate.formatted.sql=true
mondrian.rolap.maxSqlThreads=1000
3、其他方式
(1)使用聚合表
聚合表是數據倉庫中包含事實數據的匯總信息的表
(2)建立物化視圖
將查詢的結果集先通過建立視圖,定時跑批數據到視圖中,直接查詢視圖得到結果,避免了查詢時去計算。
簡化計算和查詢過程。
(3)退化維度
如果一個維度有很多可能,如學校作為維度有很多值。
這時候不再使用學校ID和表關聯,而是直接將學校名稱寫到和他關聯的表里面去。
這樣就相當於少關聯一張表,加快查詢的效率。