优化数据库查询

This commit is contained in:
squallzhjch
2023-10-19 14:47:15 +08:00
parent 202e2b3a8e
commit 129c48f11d
10 changed files with 352 additions and 108 deletions

View File

@@ -24,7 +24,10 @@ open class ReferenceEntity() : RealmObject() {
var zoomMax: Int = 23 //显示最大级别
var taskId: Int = 0 //任务ID
var enable:Int = 0 // 默认0不是显示 1为渲染显示
var tileXMin:Int =0
var tileXMax:Int = 0
var tileYMin:Int =0
var tileYMax:Int = 0
var geometry: String = "" // 要素渲染参考的geometry该数据可能会在导入预处理环节被修改原始geometry会保存在properties的geometry字段下
get() {
wkt = GeometryTools.createGeometry(field)
@@ -34,7 +37,13 @@ open class ReferenceEntity() : RealmObject() {
field = value
// 根据geometry自动计算当前要素的x-tile和y-tile
GeometryToolsKt.getTileXByGeometry(value, tileX)
tileXMin = tileX.min()
tileXMax = tileX.max()
GeometryToolsKt.getTileYByGeometry(value, tileY)
tileYMin = tileY.min()
tileYMax = tileY.max()
// 根据传入的geometry文本自动转换为Geometry对象
try {
wkt = GeometryTools.createGeometry(value)

View File

@@ -34,7 +34,15 @@ open class RenderEntity() : RealmObject(), Parcelable {
field = value
// 根据geometry自动计算当前要素的x-tile和y-tile
GeometryToolsKt.getTileXByGeometry(value, tileX)
tileXMin = tileX.min()
tileXMax = tileX.max()
GeometryToolsKt.getTileYByGeometry(value, tileY)
tileYMin = tileY.min()
tileYMax = tileY.max()
// 根据传入的geometry文本自动转换为Geometry对象
try {
wkt = GeometryTools.createGeometry(value)
@@ -58,6 +66,10 @@ open class RenderEntity() : RealmObject(), Parcelable {
var properties: RealmDictionary<String> = RealmDictionary()
var tileX: RealmSet<Int> = RealmSet() // x方向的tile编码
var tileY: RealmSet<Int> = RealmSet() // y方向的tile编码
var tileXMin:Int =0
var tileXMax:Int = 0
var tileYMin:Int =0
var tileYMax:Int = 0
var taskId: Int = 0 //任务ID
var zoomMin: Int = 18 //显示最小级别
var zoomMax: Int = 23 //显示最大级别

View File

@@ -224,7 +224,6 @@ private class MyLocationListener(callback: (BDLocation) -> Unit) : BDAbstractLoc
val call = callback;
override fun onReceiveLocation(location: BDLocation) {
call(location)
Log.e("jingo", "定位结果:速度=" + location.speed + " 方向=" + location.direction)
}
}

View File

@@ -6,6 +6,7 @@ import android.util.Log;
import androidx.annotation.RequiresApi;
import com.navinfo.collect.library.data.entity.ReferenceEntity;
import com.navinfo.collect.library.data.entity.RenderEntity;
import com.navinfo.collect.library.system.Constant;
import com.navinfo.collect.library.utils.GeometryTools;
import com.navinfo.collect.library.utils.MapParamUtils;
@@ -17,6 +18,7 @@ import org.oscim.tiling.ITileDataSink;
import org.oscim.tiling.ITileDataSource;
import org.oscim.tiling.QueryResult;
import java.util.ArrayList;
import java.util.List;
import java.util.stream.Collectors;
@@ -43,12 +45,14 @@ public class OMDBReferenceDataSource implements ITileDataSource {
public void query(MapTile tile, ITileDataSink mapDataSink) {
// 获取tile对应的坐标范围
if (tile.zoomLevel >= Constant.OMDB_MIN_ZOOM && tile.zoomLevel <= Constant.DATA_ZOOM) {
Realm realm = Realm.getInstance(MapParamUtils.getTaskConfig());
RealmQuery<ReferenceEntity> realmQuery = realm.where(ReferenceEntity.class);
int m = Constant.DATA_ZOOM - tile.zoomLevel;
int xStart = tile.tileX;
int xEnd = tile.tileX + 1;
int yStart = tile.tileY;
int yEnd = tile.tileY + 1;
if (m>0) {
if (m > 0) {
xStart = (int) (xStart << m);
xEnd = (int) (xEnd << m);
yStart = (int) (yStart << m);
@@ -56,21 +60,22 @@ public class OMDBReferenceDataSource implements ITileDataSource {
}
final int currentTileX = xStart;
if(isUpdate){
Realm.getInstance(MapParamUtils.getTaskConfig()).refresh();
if (isUpdate) {
realm.refresh();
isUpdate = false;
}
String sql = " tileX>=" + xStart + " and tileX<=" + xEnd + " and tileY>=" + yStart + " and tileY<=" + yEnd + "";
String sql = " ((tileXMin <= " + xStart + " and tileXMax >= " + xStart + ") or (tileXMin <=" + xEnd + " and tileXMax >=" + xStart + ")) and ((tileYMin <= " + yStart + " and tileYMax >= " + yStart + ") or (tileYMin <=" + yEnd + " and tileYMin >=" + yStart + "))";
if(MapParamUtils.getDataLayerEnum()!=null){
// String sql = " tileX>=" + xStart + " and tileX<=" + xEnd + " and tileY>=" + yStart + " and tileY<=" + yEnd + "";
if (MapParamUtils.getDataLayerEnum() != null) {
sql += " and enable" + MapParamUtils.getDataLayerEnum().getSql();
}else{
} else {
sql += " and enable>=0";
}
RealmQuery<ReferenceEntity> realmQuery = Realm.getInstance(MapParamUtils.getTaskConfig()).where(ReferenceEntity.class)
.rawPredicate(sql);
realmQuery.rawPredicate(sql);
// 筛选不显示的数据
if (Constant.HAD_LAYER_INVISIABLE_ARRAY != null && Constant.HAD_LAYER_INVISIABLE_ARRAY.length > 0) {
realmQuery.beginGroup();
@@ -91,10 +96,11 @@ public class OMDBReferenceDataSource implements ITileDataSource {
} else {
mapDataSink.completed(QueryResult.SUCCESS);
}
Realm.getInstance(MapParamUtils.getTaskConfig()).close();
realm.close();
} else {
mapDataSink.completed(QueryResult.SUCCESS);
}
}
@Override
@@ -109,8 +115,8 @@ public class OMDBReferenceDataSource implements ITileDataSource {
}
}
public void update(){
public void update() {
isUpdate = true;
Log.e("qj",Thread.currentThread().getName());
Log.e("qj", Thread.currentThread().getName());
}
}

View File

@@ -11,21 +11,45 @@ import com.navinfo.collect.library.utils.GeometryTools;
import com.navinfo.collect.library.utils.MapParamUtils;
import org.locationtech.jts.geom.Polygon;
import org.oscim.core.MapPosition;
import org.oscim.layers.tile.MapTile;
import org.oscim.map.Map;
import org.oscim.map.Viewport;
import org.oscim.tiling.ITileDataSink;
import org.oscim.tiling.ITileDataSource;
import org.oscim.tiling.QueryResult;
import java.util.ArrayList;
import java.util.HashMap;
import java.util.List;
import java.util.stream.Collectors;
import io.realm.Realm;
import io.realm.RealmConfiguration;
import io.realm.RealmQuery;
public class OMDBTileDataSource implements ITileDataSource {
class RealmObject {
int threadCode;
int realmConfigCode;
Realm realm;
}
// class DataObject {
// int threadCode = 0;
// byte zoom = 0;
// String lonLat = "";
// List<String> listIds = new ArrayList<>();
// }
private boolean isUpdate;
private Viewport viewport;
private List<RealmObject> realmObjectList = new ArrayList<>();
// private List<DataObject> dataObjectList = new ArrayList<>();
private final ThreadLocal<OMDBDataDecoder> mThreadLocalDecoders = new ThreadLocal<OMDBDataDecoder>() {
@Override
protected OMDBDataDecoder initialValue() {
@@ -42,12 +66,46 @@ public class OMDBTileDataSource implements ITileDataSource {
public void query(MapTile tile, ITileDataSink mapDataSink) {
// 获取tile对应的坐标范围
if (tile.zoomLevel >= Constant.OMDB_MIN_ZOOM && tile.zoomLevel <= Constant.DATA_ZOOM) {
Realm realm = null;
int threadCode = Thread.currentThread().hashCode();
// MapPosition pos = new MapPosition();
// viewport.getMapPosition(pos);
// DataObject newDataObject = new DataObject();
// newDataObject.zoom = tile.zoomLevel;
// newDataObject.threadCode = threadCode;
// newDataObject.lonLat = pos.getX() + "," + pos.getY();
synchronized (realmObjectList) {
int configCode = MapParamUtils.getTaskConfig().hashCode();
for (RealmObject object : realmObjectList) {
if (object.threadCode == threadCode) {
if (object.realmConfigCode == configCode) {
realm = object.realm;
} else {
object.realm.close();
realmObjectList.remove(object);
}
break;
}
}
if (realm == null) {
realm = Realm.getInstance(MapParamUtils.getTaskConfig());
RealmObject o = new RealmObject();
o.threadCode = threadCode;
o.realmConfigCode = configCode;
o.realm = realm;
realmObjectList.add(o);
}
}
// Log.e("jingo", " " + Realm.getDefaultInstance().hashCode() + " " + Realm.getInstance(MapParamUtils.getTaskConfig()).hashCode());
// Realm realm = Realm.getInstance(MapParamUtils.getTaskConfig());
RealmQuery<RenderEntity> realmQuery = realm.where(RenderEntity.class);
int m = Constant.DATA_ZOOM - tile.zoomLevel;
int xStart = tile.tileX;
int xEnd = tile.tileX + 1;
int yStart = tile.tileY;
int yEnd = tile.tileY + 1;
if (m>0) {
if (m > 0) {
xStart = (int) (xStart << m);
xEnd = (int) (xEnd << m);
yStart = (int) (yStart << m);
@@ -55,20 +113,28 @@ public class OMDBTileDataSource implements ITileDataSource {
}
final int currentTileX = xStart;
if(isUpdate){
Realm.getInstance(MapParamUtils.getTaskConfig()).refresh();
if (isUpdate) {
realm.refresh();
isUpdate = false;
}
String sql =" tileX>=" + xStart + " and tileX<=" + xEnd + " and tileY>=" + yStart + " and tileY<=" + yEnd + "";
if(MapParamUtils.getDataLayerEnum()!=null){
String sql = " ((tileXMin <= " + xStart + " and tileXMax >= " + xStart + ") or (tileXMin <=" + xEnd + " and tileXMax >=" + xStart + ")) and ((tileYMin <= " + yStart + " and tileYMax >= " + yStart + ") or (tileYMin <=" + yEnd + " and tileYMin >=" + yStart + "))";
if (MapParamUtils.getDataLayerEnum() != null) {
sql += " and enable" + MapParamUtils.getDataLayerEnum().getSql();
}else{
} else {
sql += " and enable>=0";
}
RealmQuery<RenderEntity> realmQuery = Realm.getInstance(MapParamUtils.getTaskConfig()).where(RenderEntity.class).rawPredicate(sql);
realmQuery.rawPredicate(sql);
if (MapParamUtils.getDataLayerEnum() != null) {
MapParamUtils.getDataLayerEnum().getSql();
}
// realmQuery.greaterThanOrEqualTo("tileXMin", xStart);
// realmQuery.lessThanOrEqualTo("tileXMax", xEnd);
// realmQuery.greaterThanOrEqualTo("tileYMin", yStart);
// realmQuery.lessThanOrEqualTo("tileYMax", yEnd);
// realmQuery.like("geometry","116.31509664888955 39.83318797612014 0");
// 筛选不显示的数据
if (Constant.HAD_LAYER_INVISIABLE_ARRAY != null && Constant.HAD_LAYER_INVISIABLE_ARRAY.length > 0) {
realmQuery.beginGroup();
@@ -77,13 +143,47 @@ public class OMDBTileDataSource implements ITileDataSource {
}
realmQuery.endGroup();
}
long time = System.currentTimeMillis();
List<RenderEntity> listResult = realmQuery/*.distinct("id")*/.findAll();
long newTime = System.currentTimeMillis() - time;
Log.e("jingo", "当前OMDBTileDataSource " + Thread.currentThread().hashCode() + " 当前realm " + realm.hashCode() + " 查询耗时" + newTime );
// 数据记录的tile号是以正外接tile号列表此处过滤并未与当前tile相交的数据
if (!listResult.isEmpty()) {
Polygon tilePolygon = GeometryTools.getTilePolygon(tile);
System.out.println("第一条数据的最小x值:" + listResult.get(0).getTileX().stream().min(Integer::compare).get());
System.out.println("当前tile的:" + listResult.get(0).getTileX().stream().min(Integer::compare).get());
listResult = listResult.stream().filter((RenderEntity renderEntity) -> renderEntity.getWkt().intersects(tilePolygon))
// System.out.println("第一条数据的最小x值:" + listResult.get(0).getTileX().stream().min(Integer::compare).get());
// System.out.println("当前tile的:" + listResult.get(0).getTileX().stream().min(Integer::compare).get());
// synchronized (dataObjectList) {
// int index = -1;
// for (int i = 0; i < dataObjectList.size(); i++) {
// DataObject dataObject = dataObjectList.get(i);
// if (dataObject.threadCode == newDataObject.threadCode) {
// index = i;
// } else if (dataObject.zoom == tile.zoomLevel && dataObject.lonLat.equals(newDataObject.lonLat)) {
// listResult = listResult.stream().filter((RenderEntity renderEntity) -> {
// for (String id : dataObject.listIds) {
// if (id.equals(renderEntity.getId())) {
// return false;
// }
// }
// return renderEntity.getWkt().intersects(tilePolygon);
// })
// /*过滤数据只有最小x屏幕的最小x或数据的最小x会被渲染跨Tile的其他数据不再重复渲染*/
//// .filter((RenderEntity renderEntity) -> MercatorProjection.longitudeToTileX(viewport.fromScreenPoint(0,0).getLongitude(), (byte) Constant.DATA_ZOOM) == currentTileX || renderEntity.getTileX().stream().min(Integer::compare).get() == currentTileX)
// .collect(Collectors.toList());
// }
// }
// if (index > -1) {
// dataObjectList.remove(index);
// }
// for (RenderEntity renderEntity : listResult) {
// newDataObject.listIds.add(renderEntity.getId());
// }
// dataObjectList.add(newDataObject);
// }
listResult = listResult.stream().filter((RenderEntity renderEntity) ->
renderEntity.getWkt().intersects(tilePolygon)
)
/*过滤数据只有最小x屏幕的最小x或数据的最小x会被渲染跨Tile的其他数据不再重复渲染*/
// .filter((RenderEntity renderEntity) -> MercatorProjection.longitudeToTileX(viewport.fromScreenPoint(0,0).getLongitude(), (byte) Constant.DATA_ZOOM) == currentTileX || renderEntity.getTileX().stream().min(Integer::compare).get() == currentTileX)
.collect(Collectors.toList());
@@ -92,10 +192,12 @@ public class OMDBTileDataSource implements ITileDataSource {
} else {
mapDataSink.completed(QueryResult.SUCCESS);
}
Realm.getInstance(MapParamUtils.getTaskConfig()).close();
// realm.close();
} else {
mapDataSink.completed(QueryResult.SUCCESS);
}
}
@Override
@@ -110,8 +212,8 @@ public class OMDBTileDataSource implements ITileDataSource {
}
}
public void update(){
public void update() {
isUpdate = true;
Log.e("qj",Thread.currentThread().getName());
Log.e("qj", Thread.currentThread().getName());
}
}