性能优化与最佳实践
第十九章 性能优化与最佳实践
19.1 性能优化概述
19.1.1 性能瓶颈来源
| 来源 | 表现 | 优化方向 |
|---|---|---|
| 数据量 | 大文件加载慢 | 数据简化、索引 |
| 渲染 | 地图绘制卡顿 | 简化符号、缓存 |
| 内存 | 程序崩溃 | 优化数据结构 |
| IO | 读写慢 | SSD、缓存 |
| 网络 | Web服务响应慢 | 缓存、代理 |
19.2 数据优化
19.2.1 空间索引
创建空间索引:
# Shapefile
processing.run("native:createspatialindex", {'INPUT': layer})
# PostGIS
# CREATE INDEX idx_geom ON table USING GIST(geom);
# SpatiaLite
# SELECT CreateSpatialIndex('table', 'geometry');
19.2.2 几何简化
# 简化几何
result = processing.run("native:simplifygeometries", {
'INPUT': layer,
'METHOD': 0, # Douglas-Peucker
'TOLERANCE': 10,
'OUTPUT': 'memory:'
})
19.2.3 数据分块
# 按网格分割大数据集
result = processing.run("native:creategrid", {
'TYPE': 2, # Rectangle
'EXTENT': layer.extent(),
'HSPACING': 10000,
'VSPACING': 10000,
'OUTPUT': 'memory:'
})
# 按网格裁剪
for grid_feature in grid_layer.getFeatures():
result = processing.run("native:clip", {
'INPUT': layer,
'OVERLAY': grid_feature.geometry(),
'OUTPUT': f'/output/tile_{grid_feature.id()}.gpkg'
})
19.2.4 使用高效格式
推荐格式:
- GeoPackage(比Shapefile高效)
- FlatGeobuf(流式处理)
- Cloud Optimized GeoTIFF(栅格)
- 空间数据库(大量数据)
# 转换为GeoPackage
processing.run("native:package", {
'LAYERS': [layer1, layer2],
'OUTPUT': '/output/data.gpkg',
'OVERWRITE': True
})
19.3 渲染优化
19.3.1 简化比例尺
设置 > 选项 > 渲染
简化阈值: 1.0
按比例简化
19.3.2 图层比例尺依赖
# 设置图层可见比例尺
layer.setMinimumScale(1000000) # 最小比例尺
layer.setMaximumScale(1000) # 最大比例尺
layer.setScaleBasedVisibility(True)
19.3.3 使用缓存
设置 > 选项 > 渲染
渲染缓存: 启用
19.3.4 金字塔/概览图
栅格金字塔:
图层属性 > 金字塔 > 构建金字塔
矢量简化图层:
为不同比例尺准备不同详细程度的图层。
19.3.5 符号优化
避免复杂符号:
- 减少符号图层数
- 避免复杂图案填充
- 使用简单形状
# 简单符号比复杂符号渲染快
simple = QgsMarkerSymbol.createSimple({'name': 'circle', 'size': '3'})
# 比多层叠加符号快很多
19.4 内存管理
19.4.1 及时释放资源
# 删除不需要的图层
QgsProject.instance().removeMapLayer(layer.id())
# 显式清理
del layer
# 强制垃圾回收
import gc
gc.collect()
19.4.2 使用迭代器
# 好的做法:使用迭代器
for feature in layer.getFeatures():
# 处理feature
pass
# 避免:一次性加载所有要素到列表
# features = list(layer.getFeatures()) # 大数据集会消耗大量内存
19.4.3 限制请求
# 只获取需要的字段
request = QgsFeatureRequest()
request.setSubsetOfAttributes(['id', 'name'], layer.fields())
# 限制几何
request.setFlags(QgsFeatureRequest.NoGeometry)
# 限制数量
request.setLimit(1000)
# 空间过滤
request.setFilterRect(extent)
19.4.4 分批处理
# 分批处理大数据
batch_size = 1000
features = layer.getFeatures()
batch = []
for feature in features:
batch.append(feature)
if len(batch) >= batch_size:
process_batch(batch)
batch = []
# 处理剩余
if batch:
process_batch(batch)
19.5 Processing优化
19.5.1 使用临时输出
# 使用内存输出(小数据)
result = processing.run("native:buffer", {
'INPUT': layer,
'OUTPUT': 'memory:'
})
# 使用临时文件(大数据)
result = processing.run("native:buffer", {
'INPUT': layer,
'OUTPUT': QgsProcessingContext().tempFilePath('.gpkg')
})
19.5.2 禁用不需要的输出
# 只获取需要的输出
result = processing.run("native:buffer", {
'INPUT': layer,
'OUTPUT': 'memory:'
})
# 只使用result['OUTPUT']
19.5.3 并行执行
from concurrent.futures import ProcessPoolExecutor
def run_analysis(params):
return processing.run("native:buffer", params)
# 并行执行多个分析
with ProcessPoolExecutor(max_workers=4) as executor:
results = list(executor.map(run_analysis, param_list))
19.6 数据库优化
19.6.1 查询优化
-- 使用空间索引
SELECT * FROM table
WHERE ST_Intersects(geom, ST_MakeEnvelope(100, 30, 120, 45, 4326))
-- 避免全表扫描
-- 使用 LIMIT
-- 只选择需要的列
SELECT id, name FROM table LIMIT 1000
19.6.2 连接池
# QGIS自动管理数据库连接
# 对于自定义应用,使用连接池
from sqlalchemy import create_engine
from sqlalchemy.pool import QueuePool
engine = create_engine(
'postgresql://user:pass@host/db',
poolclass=QueuePool,
pool_size=5,
max_overflow=10
)
19.6.3 服务端处理
-- 在数据库端完成计算
SELECT
region_name,
COUNT(*) as point_count,
SUM(population) as total_pop
FROM points p
JOIN regions r ON ST_Within(p.geom, r.geom)
GROUP BY region_name
19.7 网络优化
19.7.1 启用缓存
设置 > 选项 > 网络 > 缓存
目录: /path/to/cache
大小: 500 MB
19.7.2 代理设置
设置 > 选项 > 网络 > 代理
启用代理加速访问
19.7.3 本地瓦片缓存
# 使用本地瓦片缓存
# 配置XYZ瓦片源时使用本地缓存服务
19.8 项目优化
19.8.1 项目设置
项目 > 属性 > 通用
- 评估默认值: 仅在需要时
- 自动事务分组: 按需启用
19.8.2 减少图层数量
- 合并相似图层
- 使用规则渲染代替多图层
- 移除不需要的图层
19.8.3 优化启动
设置 > 选项 > 通用
- 检查QGIS版本: 禁用
- 加载插件: 只加载必要的
19.9 最佳实践
19.9.1 数据管理
| 实践 | 说明 |
|---|---|
| 使用GeoPackage | 比Shapefile更高效 |
| 创建空间索引 | 加速空间查询 |
| 数据分层 | 按比例尺使用不同详细程度 |
| 定期清理 | 删除临时文件和缓存 |
19.9.2 项目管理
| 实践 | 说明 |
|---|---|
| 相对路径 | 便于项目迁移 |
| 模板使用 | 标准化项目设置 |
| 版本控制 | 跟踪项目变更 |
| 文档记录 | 记录数据源和处理步骤 |
19.9.3 代码实践
# 使用上下文管理器
with edit(layer):
layer.addFeature(feature)
# 批量操作
layer.startEditing()
layer.dataProvider().addFeatures(features)
layer.commitChanges()
# 错误处理
try:
result = processing.run(...)
except QgsProcessingException as e:
print(f"处理错误: {e}")
19.9.4 工作流程
- 数据准备:清洗、转换、索引
- 测试小样本:在小数据集上测试
- 监控性能:观察内存和CPU使用
- 渐进处理:分批处理大数据
- 结果验证:检查输出正确性
19.10 性能监控
19.10.1 日志分析
视图 > 面板 > 日志消息
19.10.2 渲染时间
# 获取渲染时间
canvas = iface.mapCanvas()
canvas.renderStarting.connect(lambda: print("开始渲染"))
canvas.renderComplete.connect(lambda: print("渲染完成"))
19.10.3 内存使用
import psutil
# 监控内存使用
process = psutil.Process()
print(f"内存使用: {process.memory_info().rss / 1024 / 1024:.2f} MB")
19.11 小结
本章介绍了QGIS性能优化方法:
关键要点:
- 使用空间索引加速查询
- 简化几何和符号减少渲染负担
- 合理管理内存和资源
- 优化数据库查询
- 使用缓存提高网络性能
- 遵循最佳实践
性能优化是高效使用QGIS的关键。
上一章:第18章 高级功能与扩展
下一章:第20章 实战案例与项目应用

浙公网安备 33010602011771号