-
Notifications
You must be signed in to change notification settings - Fork 2
Expand file tree
/
Copy pathvector.html
More file actions
803 lines (753 loc) · 62 KB
/
vector.html
File metadata and controls
803 lines (753 loc) · 62 KB
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
242
243
244
245
246
247
248
249
250
251
252
253
254
255
256
257
258
259
260
261
262
263
264
265
266
267
268
269
270
271
272
273
274
275
276
277
278
279
280
281
282
283
284
285
286
287
288
289
290
291
292
293
294
295
296
297
298
299
300
301
302
303
304
305
306
307
308
309
310
311
312
313
314
315
316
317
318
319
320
321
322
323
324
325
326
327
328
329
330
331
332
333
334
335
336
337
338
339
340
341
342
343
344
345
346
347
348
349
350
351
352
353
354
355
356
357
358
359
360
361
362
363
364
365
366
367
368
369
370
371
372
373
374
375
376
377
378
379
380
381
382
383
384
385
386
387
388
389
390
391
392
393
394
395
396
397
398
399
400
401
402
403
404
405
406
407
408
409
410
411
412
413
414
415
416
417
418
419
420
421
422
423
424
425
426
427
428
429
430
431
432
433
434
435
436
437
438
439
440
441
442
443
444
445
446
447
448
449
450
451
452
453
454
455
456
457
458
459
460
461
462
463
464
465
466
467
468
469
470
471
472
473
474
475
476
477
478
479
480
481
482
483
484
485
486
487
488
489
490
491
492
493
494
495
496
497
498
499
500
501
502
503
504
505
506
507
508
509
510
511
512
513
514
515
516
517
518
519
520
521
522
523
524
525
526
527
528
529
530
531
532
533
534
535
536
537
538
539
540
541
542
543
544
545
546
547
548
549
550
551
552
553
554
555
556
557
558
559
560
561
562
563
564
565
566
567
568
569
570
571
572
573
574
575
576
577
578
579
580
581
582
583
584
585
586
587
588
589
590
591
592
593
594
595
596
597
598
599
600
601
602
603
604
605
606
607
608
609
610
611
612
613
614
615
616
617
618
619
620
621
622
623
624
625
626
627
628
629
630
631
632
633
634
635
636
637
638
639
640
641
642
643
644
645
646
647
648
649
650
651
652
653
654
655
656
657
658
659
660
661
662
663
664
665
666
667
668
669
670
671
672
673
674
675
676
677
678
679
680
681
682
683
684
685
686
687
688
689
690
691
692
693
694
695
696
697
698
699
700
701
702
703
704
705
706
707
708
709
710
711
712
713
714
715
716
717
718
719
720
721
722
723
724
725
726
727
728
729
730
731
732
733
734
735
736
737
738
739
740
741
742
743
744
745
746
747
748
749
750
751
752
753
754
755
756
757
758
759
760
761
762
763
764
765
766
767
768
769
770
771
772
773
774
775
776
777
778
779
780
781
782
783
784
785
786
787
788
789
790
791
792
793
794
795
796
797
798
799
800
801
802
803
<!DOCTYPE html>
<html lang="en" data-content_root="../">
<head>
<meta charset="utf-8" />
<meta name="viewport" content="width=device-width, initial-scale=1.0" /><meta name="viewport" content="width=device-width, initial-scale=1" />
<title>Vector Data Management & Optimization — MapServer 8.6.1 documentation</title>
<link rel="stylesheet" type="text/css" href="../_static/pygments.css?v=03e43079" />
<link rel="stylesheet" type="text/css" href="../_static/sphinx.css?v=48f05237" />
<link rel="stylesheet" type="text/css" href="../_static/copybutton.css?v=76b2166b" />
<link rel="stylesheet" type="text/css" href="../_static/custom.css?v=dd298242" />
<link rel="stylesheet" type="text/css" href="../_static/ribbon.css?v=ea091bf4" />
<script src="../_static/jquery.js?v=5d32c60e"></script>
<script src="../_static/_sphinx_javascript_frameworks_compat.js?v=2cd50e6c"></script>
<script src="../_static/documentation_options.js?v=ad95d4c4"></script>
<script src="../_static/doctools.js?v=fd6eb6e6"></script>
<script src="../_static/sphinx_highlight.js?v=6ffebe34"></script>
<script src="../_static/clipboard.min.js?v=a7894cd8"></script>
<script src="../_static/copybutton.js?v=f281be69"></script>
<link rel="icon" href="../_static/mapserver.ico"/>
<link rel="author" title="About these documents" href="../about.html" />
<link rel="index" title="Index" href="../genindex.html" />
<link rel="search" title="Search" href="../search.html" />
<link rel="copyright" title="Copyright" href="../copyright.html" />
<link rel="next" title="Utilities" href="../utilities/index.html" />
<link rel="prev" title="Tile Indexes" href="tileindex.html" />
</head><body>
<!-- for main branch only, do not backport this -->
<table width="100%" style="width: 100%; background-color: white;">
<tr>
<td rowspan="2" style="padding: 10px 0px 10px 10px;">
<a href="../index.html" title="Home"><img src="../_static/banner.png" alt="MapServer banner" border="0" /></a>
</td>
<td style="padding: 10px 10px 0px 0px; text-align: right; vertical-align: top;">
<a href="../index.html" title="Home">Home</a> |
<a href="../products.html" title="Products (MapServer core, MapCache, TinyOWS">Products</a> |
<a href="https://github.com/mapserver/mapserver/issues/" title="Issue Tracker (MapServer core)">Issue Tracker</a> |
<a href="../community/service_providers.html" title="Professional Service Providers">Service Providers</a> |
<a href="../faq.html" title="Frequently Asked Questions">FAQ</a> |
<a href="https://fosstodon.org/@mapserver" title="Mastodon" target="_blank">Mastodon</a> |
<a href="../download.html" title="Download Source or Binaries">Download </a> |
<a class="badge" href="https://www.paypal.com/cgi-bin/webscr?cmd=_s-xclick&hosted_button_id=KRJ2X44N3HA6U&source=url" target="_blank">
<img src="https://img.shields.io/badge/donate-%E2%9D%A4%C2%A0-ff69b4.svg?style=flat" alt="Donate to MapServer">
</a>
</td>
</tr>
<tr>
<td style="padding: 0px 10px 0px 0px; text-align: right; vertical-align: bottom;">
<img src="../_static/flagicons/en.png" alt="en" title="en" border="0" width="18px" height="13px"/>
<a href="../ar/optimization/vector.html"><img src="../_static/flagicons/ar.png" alt="ar" title="ar" border="0" /></a>
<a href="../de/optimization/vector.html"><img src="../_static/flagicons/de.png" alt="de" title="de" border="0" /></a>
<a href="../el/optimization/vector.html"><img src="../_static/flagicons/el.png" alt="el" title="el" border="0" /></a>
<a href="../es/optimization/vector.html"><img src="../_static/flagicons/es.png" alt="es" title="es" border="0" /></a>
<a href="../fr/optimization/vector.html"><img src="../_static/flagicons/fr.png" alt="fr" title="fr" border="0" /></a>
<a href="../id/optimization/vector.html"><img src="../_static/flagicons/id.png" alt="id" title="id" border="0" /></a>
<a href="../it/optimization/vector.html"><img src="../_static/flagicons/it.png" alt="it" title="it" border="0" /></a>
<a href="../ja/optimization/vector.html"><img src="../_static/flagicons/ja.png" alt="ja" title="ja" border="0" /></a>
<a href="../nl_NL/optimization/vector.html"><img src="../_static/flagicons/nl_NL.png" alt="nl_NL" title="nl_NL" border="0" /></a>
<a href="../pl/optimization/vector.html"><img src="../_static/flagicons/pl.png" alt="pl" title="pl" border="0" /></a>
<a href="../ru/optimization/vector.html"><img src="../_static/flagicons/ru.png" alt="ru" title="ru" border="0" /></a>
<a href="../sq/optimization/vector.html"><img src="../_static/flagicons/sq.png" alt="sq" title="sq" border="0" /></a>
<a href="../tr/optimization/vector.html"><img src="../_static/flagicons/tr.png" alt="tr" title="tr" border="0" /></a>
</td>
</tr>
</table>
<div class="related" role="navigation" aria-label="Related">
<h3>Navigation</h3>
<ul>
<li class="right" style="margin-right: 10px">
<a href="../genindex.html" title="General Index"
accesskey="I">index</a></li>
<li class="right" >
<a href="../utilities/index.html" title="Utilities"
accesskey="N">next</a> |</li>
<li class="right" >
<a href="tileindex.html" title="Tile Indexes"
accesskey="P">previous</a> |</li>
<li class="nav-item nav-item-0"><a href="../index.html">Home</a> »</li>
<li class="nav-item nav-item-1"><a href="../documentation.html" >MapServer 8.6.1 Documentation</a> »</li>
<li class="nav-item nav-item-2"><a href="index.html" accesskey="U">Optimization</a> »</li>
<li class="nav-item nav-item-this"><a href="">Vector Data Management & Optimization</a></li>
</ul>
</div>
<div class="document">
<div class="documentwrapper">
<div class="bodywrapper">
<div class="body" role="main">
<section id="vector-data-management-optimization">
<span id="vector-optimization"></span><span id="index-0"></span><h1><a class="toc-backref" href="#table-of-contents" role="doc-backlink">Vector Data Management & Optimization</a><a class="headerlink" href="#vector-data-management-optimization" title="Link to this heading">¶</a></h1>
<dl class="field-list simple">
<dt class="field-odd">Author<span class="colon">:</span></dt>
<dd class="field-odd"><p>Jeff McKenna</p>
</dd>
<dt class="field-even">Contact<span class="colon">:</span></dt>
<dd class="field-even"><p>jmckenna at gatewaygeomatics.com</p>
</dd>
<dt class="field-odd">Original Author<span class="colon">:</span></dt>
<dd class="field-odd"><p>HostGIS</p>
</dd>
<dt class="field-even">Last Updated<span class="colon">:</span></dt>
<dd class="field-even"><p>2026-03-29</p>
</dd>
</dl>
<nav class="contents" id="table-of-contents">
<p class="topic-title">Table of Contents</p>
<ul class="simple">
<li><p><a class="reference internal" href="#vector-data-management-optimization" id="id1">Vector Data Management & Optimization</a></p>
<ul>
<li><p><a class="reference internal" href="#choose-the-right-vector-format-for-your-needs" id="id2">Choose the right vector format for your needs</a></p></li>
<li><p><a class="reference internal" href="#spend-time-to-review-gdal-s-associated-driver-page-for-your-chosen-format" id="id3">Spend time to review GDAL’s associated driver page for your chosen format</a></p></li>
<li><p><a class="reference internal" href="#connect-to-your-data-through-ogr-gdal" id="id4">Connect to your data through OGR/GDAL</a></p></li>
<li><p><a class="reference internal" href="#learn-review-the-various-ogr-utilities-to-manage-your-vectors" id="id5">Learn & Review the various OGR utilities to manage your vectors</a></p></li>
<li><p><a class="reference internal" href="#index-your-data" id="id6">Index your data</a></p>
<ul>
<li><p><a class="reference internal" href="#tileindexing" id="id7">Tileindexing</a></p></li>
<li><p><a class="reference internal" href="#add-a-spatial-index-to-your-data" id="id8">Add a Spatial Index to your data</a></p></li>
<li><p><a class="reference internal" href="#add-an-attribute-index-to-your-data" id="id9">Add an Attribute Index to your data</a></p></li>
</ul>
</li>
<li><p><a class="reference internal" href="#splitting-your-data" id="id10">Splitting your data</a></p></li>
<li><p><a class="reference internal" href="#handling-your-vector-layers-in-the-mapfile" id="id11">Handling your vector LAYERS in the mapfile</a></p></li>
<li><p><a class="reference internal" href="#shapefile-notes" id="id12">Shapefile Notes</a></p></li>
<li><p><a class="reference internal" href="#postgis-notes" id="id13">PostGIS Notes</a></p>
<ul>
<li><p><a class="reference internal" href="#indexing-with-postgis" id="id14">Indexing with PostGIS</a></p></li>
<li><p><a class="reference internal" href="#specifying-a-unique-id-column" id="id15">Specifying a Unique ID column</a></p></li>
<li><p><a class="reference internal" href="#debugging-speed-issues-with-postgis" id="id16">Debugging speed issues with PostGIS</a></p></li>
</ul>
</li>
<li><p><a class="reference internal" href="#databases-in-general-postgis-oracle-spatialite-geopackage-microsoft-sql-server-mysql" id="id17">Databases in General (PostGIS, Oracle, SpatiaLite, GeoPackage, Microsoft SQL Server, MySQL)</a></p>
<ul>
<li><p><a class="reference internal" href="#enable-connection-pooling" id="id18">Enable Connection Pooling</a></p></li>
<li><p><a class="reference internal" href="#set-extent-at-the-layer-level-of-mapfile" id="id19">Set EXTENT at the LAYER level of mapfile</a></p></li>
<li><p><a class="reference internal" href="#verify-that-your-table-has-a-spatial-index" id="id20">Verify that your table has a Spatial Index</a></p></li>
<li><p><a class="reference internal" href="#for-wfs-services-prevent-using-default-full-extent" id="id21">For WFS services, prevent using default/full extent</a></p></li>
</ul>
</li>
</ul>
</li>
</ul>
</nav>
<section id="choose-the-right-vector-format-for-your-needs">
<h2><a class="toc-backref" href="#table-of-contents" role="doc-backlink">Choose the right vector format for your needs</a><a class="headerlink" href="#choose-the-right-vector-format-for-your-needs" title="Link to this heading">¶</a></h2>
<ul>
<li><p>The best/optimal vector data source for MapServer in terms of speed-of-display
is <a class="reference internal" href="../input/vector/shapefiles.html#shapefiles"><span class="std std-ref">Shapefile</span></a>.</p>
<div class="admonition tip">
<p class="admonition-title">Tip</p>
<p>MapServer 8.0 includes a new <a class="reference internal" href="../utilities/coshp.html#coshp"><span class="std std-ref">coshp</span></a> utility to create
‘Cloud Optimized Shapefiles’</p>
</div>
</li>
<li><p>A recent format designed for vector performance, with similar map draw
speed in MapServer as Shapefile, is <a class="reference internal" href="../input/vector/flatgeobuf.html#flatgeobuf"><span class="std std-ref">FlatGeobuf</span></a>, and is
recommended for cloud performance.</p></li>
<li><p>For databases, MapServer displays <a class="reference internal" href="../input/vector/postgis.html#input-postgis"><span class="std std-ref">PostGIS</span></a>
layers very fast, and some custom tricks are included in the MapServer source
specifically for PostGIS + MapServer draw speed. PostGIS is therefore recommended.</p></li>
<li><p><a class="reference internal" href="../input/vector/sqlite.html#sqlite"><span class="std std-ref">SpatiaLite</span></a> is recommended
for those who require a portable format, and works very well with MapServer.</p></li>
<li><p><a class="reference internal" href="../input/vector/geopackage.html#geopackage"><span class="std std-ref">GeoPackage</span></a> (“GPKG”) is also very popular for portability,
and works very well with MapServer.</p></li>
</ul>
<p>Here are some rudimentary map draw speed results, with the
MapServer 8.0 release code (running on Windows with <a class="reference external" href="https://ms4w.com">MS4W</a>):</p>
<div class="highlight-default notranslate"><div class="highlight"><pre><span></span><span class="n">FlatGeobuf</span> <span class="p">(</span><span class="n">native</span><span class="p">)</span> <span class="mf">0.008</span><span class="n">s</span>
<span class="n">Shapefile</span> <span class="p">(</span><span class="n">native</span><span class="p">)</span> <span class="mf">0.010</span><span class="n">s</span>
<span class="n">FlatGeobuf</span> <span class="p">(</span><span class="n">OGR</span><span class="p">)</span> <span class="mf">0.013</span><span class="n">s</span>
<span class="n">Shapefile</span> <span class="p">(</span><span class="n">OGR</span><span class="p">)</span> <span class="mf">0.023</span><span class="n">s</span>
<span class="n">GeoPackage</span> <span class="p">(</span><span class="n">OGR</span><span class="p">)</span> <span class="mf">0.042</span><span class="n">s</span>
<span class="n">SpatiaLite</span> <span class="p">(</span><span class="n">OGR</span><span class="p">)</span> <span class="mf">0.045</span><span class="n">s</span>
<span class="n">PostGIS</span> <span class="p">(</span><span class="n">native</span><span class="p">)</span> <span class="mf">0.053</span><span class="n">s</span>
<span class="n">GeoJSON</span> <span class="p">(</span><span class="n">OGR</span><span class="p">)</span> <span class="mf">0.089</span><span class="n">s</span>
</pre></div>
</div>
</section>
<section id="spend-time-to-review-gdal-s-associated-driver-page-for-your-chosen-format">
<h2><a class="toc-backref" href="#table-of-contents" role="doc-backlink">Spend time to review GDAL’s associated driver page for your chosen format</a><a class="headerlink" href="#spend-time-to-review-gdal-s-associated-driver-page-for-your-chosen-format" title="Link to this heading">¶</a></h2>
<p>This is a critical step, as MapServer relies on GDAL (actually the OGR part of the
project, which handles vectors) for vector data access. Each driver (OGR format)
has its own set of abilities and switches. Find your vector format and review
its options <a class="reference external" href="https://gdal.org/drivers/vector/index.html">here</a>.</p>
</section>
<section id="connect-to-your-data-through-ogr-gdal">
<h2><a class="toc-backref" href="#table-of-contents" role="doc-backlink">Connect to your data through OGR/GDAL</a><a class="headerlink" href="#connect-to-your-data-through-ogr-gdal" title="Link to this heading">¶</a></h2>
<p>For data management in MapServer, this should always be one of your first steps.
Sometimes desktop GIS programs will display a format or its attributes in a certain
way (such as in uppercase) but your data might not display in MapServer; checking
how OGR/GDAL reads your data file or database table, will help you manage
the data. The <a class="reference internal" href="../input/vector/ogr.html#ogr"><span class="std std-ref">OGR Vector Layers Through MapServer</span></a> document has excellent examples
(for <em>ogrinfo</em> and other commands) to connect to your data. Here is an
example connecting to a PostGIS database, and returning a list of spatial tables:</p>
<div class="highlight-default notranslate"><div class="highlight"><pre><span></span>ogrinfo -ro PG:"host=127.0.0.1 user=postgres password=postgres port=5432 dbname=mydb"
INFO: Open of `PG:host=127.0.0.1 user=postgres password=postgres port=5432 dbname=mydb'
using driver `PostgreSQL' successful.
1: popplace (Point)
2: province (Multi Polygon)
</pre></div>
</div>
<p>Then get a summary of the ‘popplace’ table through ogrinfo:</p>
<div class="highlight-default notranslate"><div class="highlight"><pre><span></span>ogrinfo -ro PG:"host=127.0.0.1 user=postgres password=postgres port=5433 dbname=mydb" popplace -summary
INFO: Open of `PG:host=127.0.0.1 user=postgres password=postgres port=5433 dbname=mydb'
using driver `PostgreSQL' successful.
Layer name: popplace
Geometry: Point
Feature Count: 497
Extent: (-2303861.750000, -681502.875000) - (2961766.250000, 3798856.750000)
Layer SRS WKT:
PROJCS["NAD83 / Canada Atlas Lambert",
GEOGCS["NAD83",
DATUM["North_American_Datum_1983",
SPHEROID["GRS 1980",6378137,298.257222101,
AUTHORITY["EPSG","7019"]],
TOWGS84[0,0,0,0,0,0,0],
AUTHORITY["EPSG","6269"]],
PRIMEM["Greenwich",0,
AUTHORITY["EPSG","8901"]],
UNIT["degree",0.0174532925199433,
AUTHORITY["EPSG","9122"]],
AUTHORITY["EPSG","4269"]],
PROJECTION["Lambert_Conformal_Conic_2SP"],
PARAMETER["standard_parallel_1",49],
PARAMETER["standard_parallel_2",77],
PARAMETER["latitude_of_origin",49],
PARAMETER["central_meridian",-95],
PARAMETER["false_easting",0],
PARAMETER["false_northing",0],
UNIT["metre",1,
AUTHORITY["EPSG","9001"]],
AXIS["Easting",EAST],
AXIS["Northing",NORTH],
AUTHORITY["EPSG","3978"]]
FID Column = gid
Geometry Column = geom
area: Real (0.0)
perimeter: Real (0.0)
popplace_: Real (0.0)
popplace_i: Real (0.0)
unique_key: String (5.0)
name: String (25.0)
name_e: String (20.0)
name_f: String (20.0)
reg_code: Real (0.0)
nts50: String (7.0)
lat: String (7.0)
long: String (7.0)
sgc_code: Real (0.0)
capital: Real (0.0)
pop_range: Real (0.0)
</pre></div>
</div>
<div class="admonition note">
<p class="admonition-title">Note</p>
<p>You can use the extent values returned from ogrinfo, to paste into your
mapfile’s EXTENT parameter. You can also notice in that summary
the <em>PROJCS/AUTHORITY</em> line, which states that this data is currently
in the <a class="reference external" href="https://spatialreference.org/ref/epsg/3978/">EPSG:3978</a> projection.</p>
</div>
</section>
<section id="learn-review-the-various-ogr-utilities-to-manage-your-vectors">
<h2><a class="toc-backref" href="#table-of-contents" role="doc-backlink">Learn & Review the various OGR utilities to manage your vectors</a><a class="headerlink" href="#learn-review-the-various-ogr-utilities-to-manage-your-vectors" title="Link to this heading">¶</a></h2>
<p>OGR commandline utilities are very useful, making it easy to manipulate
your source vector file or database, before display in MapServer. For example,
you might want to import a spatial file into your existing PostGIS database,
which you can do easily through
<a class="reference external" href="https://gdal.org/programs/ogr2ogr.html">ogr2ogr</a> as the following
(that takes a shapefile, imports it into an existing PostGIS database, and
renames the new table to ‘roadways’) :</p>
<div class="highlight-default notranslate"><div class="highlight"><pre><span></span><span class="n">ogr2ogr</span> <span class="n">PG</span><span class="p">:</span><span class="s2">"host=127.0.0.1 user=postgres password=postgres port=5432 dbname=mydb"</span> <span class="n">road</span><span class="o">.</span><span class="n">shp</span> <span class="o">-</span><span class="n">nln</span> <span class="n">roadways</span>
</pre></div>
</div>
<div class="admonition note">
<p class="admonition-title">Note</p>
<p>where ogr2ogr syntax is actually: <em>ogr2ogr destination source</em></p>
</div>
<p>You might also import a spatial file, and reproject it to another EPSG
projection, as the following (that takes a shapefile, reprojects it into
the web mercator <a class="reference external" href="https://spatialreference.org/ref/epsg/3857/">EPSG:3857</a>, imports it into an
existing PostGIS database, and renames the new table to ‘roadways3857’) :</p>
<div class="highlight-default notranslate"><div class="highlight"><pre><span></span><span class="n">ogr2ogr</span> <span class="o">-</span><span class="n">t_srs</span> <span class="n">EPSG</span><span class="p">:</span><span class="mi">3857</span> <span class="o">-</span><span class="n">s_srs</span> <span class="n">EPSG</span><span class="p">:</span><span class="mi">3978</span> <span class="n">PG</span><span class="p">:</span><span class="s2">"host=127.0.0.1 user=postgres password=postgres port=5432 dbname=mydb"</span> <span class="n">road</span><span class="o">.</span><span class="n">shp</span> <span class="o">-</span><span class="n">nln</span> <span class="n">roadways3857</span>
</pre></div>
</div>
<div class="admonition note">
<p class="admonition-title">Note</p>
<p>where ogr2ogr syntax is actually: <em>ogr2ogr -t_srs (ouput projection) -s_srs (source projection) destination source</em></p>
</div>
<p>Review all of the available OGR vector utilities
<a class="reference external" href="https://gdal.org/programs/#vector-programs">here</a>.</p>
</section>
<section id="index-your-data">
<h2><a class="toc-backref" href="#table-of-contents" role="doc-backlink">Index your data</a><a class="headerlink" href="#index-your-data" title="Link to this heading">¶</a></h2>
<p>This of course is an important step for any vector layer, for fast display
in MapServer. There are several types of indexes that you can enable to
speed up the display of your vector data with MapServer:</p>
<section id="tileindexing">
<h3><a class="toc-backref" href="#table-of-contents" role="doc-backlink">Tileindexing</a><a class="headerlink" href="#tileindexing" title="Link to this heading">¶</a></h3>
<p>See <a class="reference internal" href="tileindex.html#tileindex"><span class="std std-ref">Tile Indexes</span></a> for more detailed information about
on-the-fly mosaicing with MapServer.</p>
</section>
<section id="add-a-spatial-index-to-your-data">
<h3><a class="toc-backref" href="#table-of-contents" role="doc-backlink">Add a Spatial Index to your data</a><a class="headerlink" href="#add-a-spatial-index-to-your-data" title="Link to this heading">¶</a></h3>
<p>Make sure that your geometry has a spatial index.</p>
<ul class="simple">
<li><p>Shapefile: see <a class="reference internal" href="../utilities/shptree.html#shptree"><span class="std std-ref">shptree</span></a></p></li>
<li><p>See below for databases (and GPKG)</p></li>
</ul>
</section>
<section id="add-an-attribute-index-to-your-data">
<h3><a class="toc-backref" href="#table-of-contents" role="doc-backlink">Add an Attribute Index to your data</a><a class="headerlink" href="#add-an-attribute-index-to-your-data" title="Link to this heading">¶</a></h3>
<p>If you will be querying or filtering by a specific column in your
data, you should setup an attribute index on your vector data.</p>
<p>Shapefiles:</p>
<div class="highlight-default notranslate"><div class="highlight"><pre><span></span><span class="n">ogrinfo</span> <span class="o">-</span><span class="n">sql</span> <span class="s2">"CREATE INDEX ON province USING NAME_E"</span> <span class="n">province</span><span class="o">.</span><span class="n">shp</span>
</pre></div>
</div>
<p>2 files should be created with extensions: <em>.ind & .idm</em></p>
<p>GeoPackage:</p>
<div class="highlight-default notranslate"><div class="highlight"><pre><span></span><span class="n">ogrinfo</span> <span class="o">-</span><span class="n">sql</span> <span class="s2">"CREATE INDEX IDXnewindexname ON yourtable (yourcolumn)"</span> <span class="n">file</span><span class="o">.</span><span class="n">gpkg</span>
</pre></div>
</div>
</section>
</section>
<section id="splitting-your-data">
<h2><a class="toc-backref" href="#table-of-contents" role="doc-backlink">Splitting your data</a><a class="headerlink" href="#splitting-your-data" title="Link to this heading">¶</a></h2>
<p>If you find yourself making several layers, all of them using the same dataset
but filtering to only use some of the records, you could probably do it
better. If the criteria are static, one approach is to pre-split the data.</p>
<p>The <em>ogr2ogr</em> utility can select on certain features from a datasource, and
save them to a new data source. Thus, you can split your dataset into several
smaller ones that are already effectively filtered, and remove the FILTER
statement.</p>
<p>If you are using shapefiles, the <a class="reference external" href="https://github.com/woodbri/imaptools.com">shp2tile</a>
utility is a wonderful commandline tool for this.</p>
<div class="admonition note">
<p class="admonition-title">Note</p>
<p>For Windows users, <a class="reference external" href="https://ms4w.com">MS4W</a> includes the shp2tile utility, and
all utilities mentioned here.</p>
</div>
</section>
<section id="handling-your-vector-layers-in-the-mapfile">
<span id="index-1"></span><h2><a class="toc-backref" href="#table-of-contents" role="doc-backlink">Handling your vector LAYERS in the mapfile</a><a class="headerlink" href="#handling-your-vector-layers-in-the-mapfile" title="Link to this heading">¶</a></h2>
<p>Please review the notes in the document <a class="reference internal" href="mapfile.html#mapfile-tuning"><span class="std std-ref">Mapfile Tuning & Management</span></a>. You should also
check for any specific MapServer notes for your format in the <a class="reference internal" href="../input/vector/index.html#vector"><span class="std std-ref">Vector Data</span></a>
document.</p>
</section>
<section id="shapefile-notes">
<h2><a class="toc-backref" href="#table-of-contents" role="doc-backlink">Shapefile Notes</a><a class="headerlink" href="#shapefile-notes" title="Link to this heading">¶</a></h2>
<p>Use <a class="reference internal" href="../utilities/shptree.html#shptree"><span class="std std-ref">shptree</span></a> to generate a spatial index on your <a class="reference internal" href="../input/vector/shapefiles.html#shapefiles"><span class="std std-ref">shapefile</span></a>. This is
quick and easy (“shptree foo.shp”) and generates a .qix file. MapServer will
automagically detect an index and use it.</p>
<div class="admonition note">
<p class="admonition-title">Note</p>
<p>Tileindexes can also be indexed with <a class="reference internal" href="../utilities/shptree.html#shptree"><span class="std std-ref">shptree</span></a>.</p>
</div>
<p>MapServer also comes with the <a class="reference internal" href="../utilities/sortshp.html#sortshp"><span class="std std-ref">sortshp</span></a> utility. This reorganizes a
shapefile, sorting it according to the values in one of its columns. If you’re
commonly filtering by criteria and it’s almost always by a specific column,
this can make the process slightly more efficient.</p>
<p>Although shapefiles are a very fast data format, <a class="reference internal" href="../input/vector/postgis.html#input-postgis"><span class="std std-ref">PostGIS</span></a> is pretty speedy as well, especially if you use indexes well
and have memory to throw at caching.</p>
</section>
<section id="postgis-notes">
<span id="index-2"></span><h2><a class="toc-backref" href="#table-of-contents" role="doc-backlink">PostGIS Notes</a><a class="headerlink" href="#postgis-notes" title="Link to this heading">¶</a></h2>
<div class="admonition seealso">
<p class="admonition-title">See also</p>
<p><a class="reference internal" href="../input/vector/postgis.html#input-postgis"><span class="std std-ref">PostGIS Input in MapServer</span></a></p>
</div>
<section id="indexing-with-postgis">
<h3><a class="toc-backref" href="#table-of-contents" role="doc-backlink">Indexing with PostGIS</a><a class="headerlink" href="#indexing-with-postgis" title="Link to this heading">¶</a></h3>
<p>The single biggest boost to performance is indexing. Make sure that there’s a
GIST index on the geometry column, and each record should also have an indexed
primary key. If you used shp2pgsql, then these statements should create the
necessary indexes:</p>
<div class="highlight-sql notranslate"><div class="highlight"><pre><span></span><span class="k">ALTER</span><span class="w"> </span><span class="k">TABLE</span><span class="w"> </span><span class="k">table</span><span class="w"> </span><span class="k">ADD</span><span class="w"> </span><span class="k">PRIMARY</span><span class="w"> </span><span class="k">KEY</span><span class="w"> </span><span class="p">(</span><span class="n">gid</span><span class="p">);</span>
<span class="k">CREATE</span><span class="w"> </span><span class="k">INDEX</span><span class="w"> </span><span class="n">table_the_geom</span><span class="w"> </span><span class="k">ON</span><span class="w"> </span><span class="k">table</span><span class="w"> </span><span class="p">(</span><span class="n">the_geom</span><span class="p">)</span><span class="w"> </span><span class="k">USING</span><span class="w"> </span><span class="n">GIST</span><span class="p">;</span>
</pre></div>
</div>
<p>PostgreSQL also supports reorganizing the data in a table, such that it’s
physically sorted by the index. This allows PostgreSQL to be much more
efficient in reading the indexed data. Use the
<a class="reference external" href="https://www.postgresql.org/docs/current/sql-cluster.html">CLUSTER command</a>,
e.g.</p>
<div class="highlight-sql notranslate"><div class="highlight"><pre><span></span><span class="k">CLUSTER</span><span class="w"> </span><span class="n">the_geom</span><span class="w"> </span><span class="k">ON</span><span class="w"> </span><span class="k">table</span><span class="p">;</span>
</pre></div>
</div>
<p>Then there are numerous optimizations one can perform on the database server
itself, aside from the geospatial component. The easiest is to increase
<em>shared_buffers</em> in the <em>postgresql.conf</em> file, which allows PostgreSQL to use
more memory for caching. It is worth the time to investigate the various options
in the <a class="reference external" href="https://www.postgresql.org/docs/current/runtime-config-resource.html">Resource Consumption</a>
section of the PostgreSQL documentation.</p>
</section>
<section id="specifying-a-unique-id-column">
<span id="uniqueid-postgis"></span><h3><a class="toc-backref" href="#table-of-contents" role="doc-backlink">Specifying a Unique ID column</a><a class="headerlink" href="#specifying-a-unique-id-column" title="Link to this heading">¶</a></h3>
<p>To handle queries, MapServer requires a unique ID column, as part of your
PostgreSQL table. MapServer will try to guess the unique ID column, but that
is costly as several more database queries have to be made; instead, you should
always specify a unique ID column in your DATA statement of the layer, with the
<em>using unique</em> syntax, such as:</p>
<div class="highlight-mapfile notranslate"><div class="highlight"><pre><span></span><span class="k">DATA</span> <span class="s">"geom FROM mydata USING UNIQUE myid USING SRID=3857"</span>
</pre></div>
</div>
<p>If your table does not have a unique ID column, you can add one such as:</p>
<div class="highlight-default notranslate"><div class="highlight"><pre><span></span><span class="n">ALTER</span> <span class="n">TABLE</span> <span class="n">mytable</span> <span class="n">ADD</span> <span class="n">COLUMN</span> <span class="n">unique_id</span> <span class="n">SERIAL</span> <span class="n">PRIMARY</span> <span class="n">KEY</span><span class="p">;</span>
</pre></div>
</div>
<div class="admonition warning">
<p class="admonition-title">Warning</p>
<p>In older PostgreSQL versions, a (dirty) trick was to use the existing <em>OID</em> as
the unique ID, however OIDs were removed from PostgreSQL as of the PostgreSQL 12.0 release.
So always specify an actual unique ID column instead, in your layer’s
DATA statement, of your mapfile.</p>
</div>
</section>
<section id="debugging-speed-issues-with-postgis">
<span id="debugging-postgis"></span><h3><a class="toc-backref" href="#table-of-contents" role="doc-backlink">Debugging speed issues with PostGIS</a><a class="headerlink" href="#debugging-speed-issues-with-postgis" title="Link to this heading">¶</a></h3>
<p>You may face a situation where your PostGIS table is drawing slowly in MapServer.
The following steps will help you examine the issue (using a WFS case) :</p>
<div class="admonition seealso">
<p class="admonition-title">See also</p>
<p><a class="reference internal" href="debugging.html#debugging"><span class="std std-ref">Debugging MapServer</span></a></p>
</div>
<ul>
<li><p>Always start by getting the draw time for your layer, with a <a class="reference internal" href="../utilities/map2img.html#map2img"><span class="std std-ref">map2img</span></a>
command:</p>
<blockquote>
<div><div class="highlight-default notranslate"><div class="highlight"><pre><span></span><span class="n">map2img</span> <span class="o">-</span><span class="n">m</span> <span class="n">postgis</span><span class="o">-</span><span class="n">wfs</span><span class="o">.</span><span class="n">map</span> <span class="o">-</span><span class="n">o</span> <span class="n">ttt</span><span class="o">.</span><span class="n">png</span> <span class="o">-</span><span class="n">map_debug</span> <span class="mi">3</span>
<span class="n">msDrawMap</span><span class="p">():</span> <span class="n">Layer</span> <span class="mi">0</span> <span class="p">(</span><span class="n">provinces</span><span class="p">),</span> <span class="mf">1.587</span><span class="n">s</span>
<span class="n">msDrawMap</span><span class="p">():</span> <span class="n">Drawing</span> <span class="n">Label</span> <span class="n">Cache</span><span class="p">,</span> <span class="mf">0.000</span><span class="n">s</span>
<span class="n">msDrawMap</span><span class="p">()</span> <span class="n">total</span> <span class="n">time</span><span class="p">:</span> <span class="mf">1.589</span><span class="n">s</span>
<span class="n">msSaveImage</span><span class="p">(</span><span class="n">ttt</span><span class="o">.</span><span class="n">png</span><span class="p">)</span> <span class="n">total</span> <span class="n">time</span><span class="p">:</span> <span class="mf">0.005</span><span class="n">s</span>
<span class="n">freeLayer</span><span class="p">():</span> <span class="n">freeing</span> <span class="n">layer</span> <span class="n">at</span> <span class="mf">010E0</span><span class="n">EC0</span><span class="o">.</span>
<span class="n">msPostGISLayerIsOpen</span> <span class="n">called</span><span class="o">.</span>
<span class="n">msConnPoolClose</span><span class="p">(</span><span class="n">host</span><span class="o">=</span><span class="mf">127.0.0.1</span> <span class="n">user</span><span class="o">=</span><span class="n">postgres</span> <span class="n">password</span><span class="o">=</span><span class="n">postgres</span> <span class="n">port</span><span class="o">=</span><span class="mi">5432</span> <span class="n">dbname</span><span class="o">=</span><span class="n">gmap</span><span class="p">,</span><span class="mi">01197840</span><span class="p">)</span>
</pre></div>
</div>
</div></blockquote>
</li>
<li><p>To diagnose if the problem is with your PostGIS table configuration, or with
MapServer, execute the exact request sent by MapServer, at the psql.exe
commandline, by doing the following steps:</p>
<blockquote>
<div><ul>
<li><p>add into your MAP-level of your mapfile:</p>
<blockquote>
<div><div class="highlight-mapfile notranslate"><div class="highlight"><pre><span></span><span class="k">CONFIG</span> <span class="s">"CPL_DEBUG"</span> <span class="s">"ON"</span>
<span class="k">CONFIG</span> <span class="s">"MS_ERRORFILE"</span> <span class="s">"/ms4w/tmp/ms_error.txt"</span>
<span class="k">DEBUG</span> <span class="mi">5</span>
</pre></div>
</div>
</div></blockquote>
</li>
<li><p>add into your PostGIS LAYER of your mapfile:</p>
<blockquote>
<div><div class="highlight-mapfile notranslate"><div class="highlight"><pre><span></span><span class="k">DEBUG</span> <span class="mi">5</span>
</pre></div>
</div>
</div></blockquote>
</li>
<li><p>now use a WFS client such as QGIS and add your WFS PostGIS layer</p></li>
<li><p>open “/ms4w/tmp/ms_error.txt” in Notepad++</p></li>
<li><p>search for “msPostGISLayerWhichShapes query:”</p></li>
<li><p>that line should list the long exact query sent from MapServer to the
PostreSQL instance, it may look like:</p>
<blockquote>
<div><div class="highlight-default notranslate"><div class="highlight"><pre><span></span><span class="p">[</span><span class="n">Mon</span> <span class="n">Apr</span> <span class="mi">12</span> <span class="mi">11</span><span class="p">:</span><span class="mi">27</span><span class="p">:</span><span class="mi">34</span> <span class="mi">2021</span><span class="p">]</span><span class="mf">.207000</span> <span class="n">msPostGISLayerWhichShapes</span> <span class="n">query</span><span class="p">:</span>
<span class="n">SELECT</span> <span class="s2">"gid"</span><span class="p">::</span><span class="n">text</span><span class="p">,</span><span class="s2">"area"</span><span class="p">::</span><span class="n">text</span><span class="p">,</span><span class="s2">"perimeter"</span><span class="p">::</span><span class="n">text</span><span class="p">,</span><span class="s2">"province_"</span><span class="p">::</span><span class="n">text</span><span class="p">,</span><span class="s2">"province_i"</span><span class="p">::</span><span class="n">text</span><span class="p">,</span><span class="s2">"status"</span><span class="p">::</span><span class="n">text</span><span class="p">,</span><span class="s2">"name"</span><span class="p">::</span><span class="n">text</span><span class="p">,</span><span class="s2">"name_e"</span><span class="p">::</span><span class="n">text</span><span class="p">,</span><span class="s2">"name_f"</span><span class="p">::</span><span class="n">text</span><span class="p">,</span><span class="s2">"reg_code"</span><span class="p">::</span><span class="n">text</span><span class="p">,</span><span class="s2">"poly_featu"</span><span class="p">::</span><span class="n">text</span><span class="p">,</span><span class="s2">"island"</span><span class="p">::</span><span class="n">text</span><span class="p">,</span><span class="s2">"island_e"</span><span class="p">::</span><span class="n">text</span><span class="p">,</span><span class="s2">"island_f"</span><span class="p">::</span><span class="n">text</span><span class="p">,</span><span class="n">ST_AsBinary</span><span class="p">((</span><span class="s2">"geom"</span><span class="p">),</span><span class="s1">'NDR'</span><span class="p">)</span>
<span class="k">as</span> <span class="n">geom</span><span class="p">,</span><span class="s2">"gid"</span><span class="p">::</span><span class="n">text</span> <span class="n">FROM</span> <span class="n">province</span> <span class="n">WHERE</span> <span class="s2">"geom"</span> <span class="o">&&</span>
<span class="n">ST_GeomFromText</span><span class="p">(</span><span class="s1">'POLYGON((-5814679.36987815</span>
<span class="o">-</span><span class="mf">1504714.04276694</span><span class="p">,</span><span class="o">-</span><span class="mf">5814679.36987815</span> <span class="mf">4439806.52253364</span><span class="p">,</span><span class="mf">5943763.33635122</span>
<span class="mf">4439806.52253364</span><span class="p">,</span><span class="mf">5943763.33635122</span> <span class="o">-</span><span class="mf">1504714.04276694</span><span class="p">,</span><span class="o">-</span><span class="mf">5814679.36987815</span>
<span class="o">-</span><span class="mf">1504714.04276694</span><span class="p">))</span><span class="s1">',3978) LIMIT 2 OFFSET 0</span>
</pre></div>
</div>
</div></blockquote>
<div class="admonition note">
<p class="admonition-title">Note</p>
<p>For one QGIS action, there could be several queries sent to MapServer,
so also look for other “msPostGISLayerWhichShapes query:” instances in
that error log.</p>
</div>
</li>
<li><p>now connect to that database through psql.exe</p>
<blockquote>
<div><div class="highlight-default notranslate"><div class="highlight"><pre><span></span><span class="n">psql</span> <span class="o">-</span><span class="n">U</span> <span class="n">postgres</span> <span class="o">-</span><span class="n">p</span> <span class="mi">5432</span> <span class="o">-</span><span class="n">d</span> <span class="n">mydb</span>
</pre></div>
</div>
</div></blockquote>
</li>
<li><p>using that error file line, grab everything from “SELECT”, and inside
your database prompt, start the command with “EXPLAIN ANALYZE” and then
paste your full query, such as:</p>
<blockquote>
<div><div class="highlight-default notranslate"><div class="highlight"><pre><span></span><span class="n">mydb</span><span class="o">=</span><span class="c1"># EXPLAIN ANALYZE SELECT</span>
<span class="s2">"gid"</span><span class="p">::</span><span class="n">text</span><span class="p">,</span><span class="s2">"area"</span><span class="p">::</span><span class="n">text</span><span class="p">,</span><span class="s2">"perimeter"</span><span class="p">::</span><span class="n">text</span><span class="p">,</span><span class="s2">"province_"</span><span class="p">::</span><span class="n">text</span><span class="p">,</span><span class="s2">"province_i"</span><span class="p">::</span><span class="n">text</span><span class="p">,</span><span class="s2">"status"</span><span class="p">::</span><span class="n">text</span><span class="p">,</span><span class="s2">"name"</span><span class="p">::</span><span class="n">text</span><span class="p">,</span><span class="s2">"name_e"</span><span class="p">::</span><span class="n">text</span><span class="p">,</span><span class="s2">"name_f"</span><span class="p">::</span><span class="n">text</span><span class="p">,</span><span class="s2">"reg_code"</span><span class="p">::</span><span class="n">text</span><span class="p">,</span><span class="s2">"poly_featu"</span><span class="p">::</span><span class="n">text</span><span class="p">,</span><span class="s2">"island"</span><span class="p">::</span><span class="n">text</span><span class="p">,</span><span class="s2">"island_e"</span><span class="p">::</span><span class="n">text</span><span class="p">,</span><span class="s2">"island_f"</span><span class="p">::</span><span class="n">text</span><span class="p">,</span><span class="n">ST_AsBinary</span><span class="p">((</span><span class="s2">"geom"</span><span class="p">),</span><span class="s1">'NDR'</span><span class="p">)</span>
<span class="k">as</span> <span class="n">geom</span><span class="p">,</span><span class="s2">"gid"</span><span class="p">::</span><span class="n">text</span> <span class="n">FROM</span> <span class="n">province</span> <span class="n">WHERE</span> <span class="s2">"geom"</span> <span class="o">&&</span>
<span class="n">ST_GeomFromText</span><span class="p">(</span><span class="s1">'POLYGON((-5814679.36987815</span>
<span class="o">-</span><span class="mf">1504714.04276694</span><span class="p">,</span><span class="o">-</span><span class="mf">5814679.36987815</span> <span class="mf">4439806.52253364</span><span class="p">,</span><span class="mf">5943763.33635122</span>
<span class="mf">4439806.52253364</span><span class="p">,</span><span class="mf">5943763.33635122</span> <span class="o">-</span><span class="mf">1504714.04276694</span><span class="p">,</span><span class="o">-</span><span class="mf">5814679.36987815</span>
<span class="o">-</span><span class="mf">1504714.04276694</span><span class="p">))</span><span class="s1">',3978) LIMIT 2 OFFSET 0;</span>
</pre></div>
</div>
</div></blockquote>
</li>
<li><p>the response will tell you how long that query took, such as:</p>
<blockquote>
<div><div class="highlight-default notranslate"><div class="highlight"><pre><span></span><span class="n">Execution</span> <span class="n">time</span><span class="p">:</span> <span class="mf">0.293</span> <span class="n">ms</span>
</pre></div>
</div>
</div></blockquote>
</li>
<li><p>if the query takes a long time to execute at the psql commandline, then you know
to focus your efforts on improving the indexing/settings of your PostGIS table.</p></li>
</ul>
</div></blockquote>
</li>
</ul>
</section>
</section>
<section id="databases-in-general-postgis-oracle-spatialite-geopackage-microsoft-sql-server-mysql">
<span id="vector-database-optimization"></span><span id="index-3"></span><h2><a class="toc-backref" href="#table-of-contents" role="doc-backlink">Databases in General (PostGIS, Oracle, SpatiaLite, GeoPackage, Microsoft SQL Server, MySQL)</a><a class="headerlink" href="#databases-in-general-postgis-oracle-spatialite-geopackage-microsoft-sql-server-mysql" title="Link to this heading">¶</a></h2>
<section id="enable-connection-pooling">
<h3><a class="toc-backref" href="#table-of-contents" role="doc-backlink">Enable Connection Pooling</a><a class="headerlink" href="#enable-connection-pooling" title="Link to this heading">¶</a></h3>
<p>By default, MapServer opens and closes a new database connection for each
database-driven layer in the mapfile. If you have several layers reading from
the same database, this doesn’t make a lot of sense. And with some databases
(such as Oracle) establishing connections takes enough time that it can become
significant.</p>
<p>Try adding this line to your database layers:</p>
<div class="highlight-mapfile notranslate"><div class="highlight"><pre><span></span><span class="k">PROCESSING</span> <span class="s">"CLOSE_CONNECTION=DEFER"</span>
</pre></div>
</div>
<p>This causes MapServer to not close the database connection for each layer until
after it has finished processing the mapfile and this may shave a few seconds
off of map generation times.</p>
</section>
<section id="set-extent-at-the-layer-level-of-mapfile">
<h3><a class="toc-backref" href="#table-of-contents" role="doc-backlink">Set EXTENT at the LAYER level of mapfile</a><a class="headerlink" href="#set-extent-at-the-layer-level-of-mapfile" title="Link to this heading">¶</a></h3>
<p>Also for performance, each of your LAYERs with a database connection should
have <a class="reference internal" href="../mapfile/layer.html#layer-extent"><span class="std std-ref">EXTENT</span></a> set at the layer level (as well as <em>ows_extent</em> metadata if you
are serving through OGC services), such as:</p>
<blockquote>
<div><div class="highlight-mapfile notranslate"><div class="highlight"><pre><span></span><span class="o">/*</span> <span class="err">my</span> <span class="err">database</span> <span class="k">layer</span> <span class="o">*/</span>
<span class="k">LAYER</span>
<span class="k">NAME</span> <span class="s">"provinces"</span>
<span class="k">METADATA</span>
<span class="s">"wms_title"</span> <span class="s">"Land"</span>
<span class="s">"wms_extent"</span> <span class="s">"-2340603.75 -719746.0625 3009430.5 3836605.25"</span> <span class="c">#this helps for performance</span>
<span class="k">END</span> <span class="c">#metadata</span>
<span class="k">TYPE</span> <span class="nb">POLYGON</span>
<span class="k">STATUS</span> <span class="nb">ON</span>
<span class="k">CONNECTIONTYPE</span> <span class="nb">postgis</span>
<span class="k">CONNECTION</span> <span class="s">"host=127.0.0.1 user=postgres password=postgres port=5432 dbname=gmap"</span>
<span class="k">DATA</span> <span class="s">"geom FROM province USING unique gid using srid=3978"</span>
<span class="k">EXTENT</span> <span class="p">-</span><span class="mf">2340603.75</span> <span class="p">-</span><span class="mf">719746.0625</span> <span class="mf">3009430.5</span> <span class="mf">3836605.25</span> <span class="c">#this helps for performance</span>
<span class="k">PROJECTION</span>
<span class="s">"init=epsg:3978"</span>
<span class="k">END</span> <span class="c"># projection</span>
<span class="p">...</span>
<span class="k">END</span> <span class="c"># layer</span>
</pre></div>
</div>
</div></blockquote>
<div class="admonition tip">
<p class="admonition-title">Tip</p>
<p>PostGIS users can use the <a class="reference external" href="https://postgis.net/docs/ST_Extent.html">ST_Extent()</a>
spatial function to get the bounding box of a table, such as</p>
<div class="highlight-default notranslate"><div class="highlight"><pre><span></span><span class="n">SELECT</span> <span class="n">ST_Extent</span><span class="p">(</span><span class="n">geom</span><span class="p">)</span> <span class="k">as</span> <span class="n">table_extent</span> <span class="n">FROM</span> <span class="n">province</span><span class="p">;</span>
<span class="n">table_extent</span>
<span class="o">----------------------------------------------------</span>
<span class="n">BOX</span><span class="p">(</span><span class="o">-</span><span class="mf">2340603.75</span> <span class="o">-</span><span class="mf">719746.0625</span><span class="p">,</span><span class="mf">3009430.5</span> <span class="mf">3836605.25</span><span class="p">)</span>
<span class="p">(</span><span class="mi">1</span> <span class="n">row</span><span class="p">)</span>
</pre></div>
</div>
</div>
</section>
<section id="verify-that-your-table-has-a-spatial-index">
<h3><a class="toc-backref" href="#table-of-contents" role="doc-backlink">Verify that your table has a Spatial Index</a><a class="headerlink" href="#verify-that-your-table-has-a-spatial-index" title="Link to this heading">¶</a></h3>
<section id="postgresql-postgis-example">
<h4>PostgreSQL/PostGIS example<a class="headerlink" href="#postgresql-postgis-example" title="Link to this heading">¶</a></h4>
<p>Once connected through psql commandline, describe the table and
look for an “Indexes” section, mentioning geometry, such as:</p>
<div class="highlight-default notranslate"><div class="highlight"><pre><span></span><span class="n">Indexes</span><span class="p">:</span>
<span class="s2">"province_pkey"</span> <span class="n">PRIMARY</span> <span class="n">KEY</span><span class="p">,</span> <span class="n">btree</span> <span class="p">(</span><span class="n">ogc_fid</span><span class="p">)</span>
<span class="s2">"province_wkb_geometry_geom_idx"</span> <span class="n">gist</span> <span class="p">(</span><span class="n">wkb_geometry</span><span class="p">)</span>
</pre></div>
</div>
</section>
<section id="geopackage-example">
<h4>GeoPackage example<a class="headerlink" href="#geopackage-example" title="Link to this heading">¶</a></h4>
<p>You can use <em>ogrinfo</em> to verify that your GPKG table’s geometry
has a spatial index, which is very important for performance
(look for <cite>HasSpatialIndex (Integer) = 1</cite> to confirm that the spatial
index exists) :</p>
<div class="highlight-default notranslate"><div class="highlight"><pre><span></span><span class="n">ogrinfo</span> <span class="o">-</span><span class="n">sql</span> <span class="s2">"SELECT HasSpatialIndex('countries', 'GEOMETRY')"</span> <span class="n">countries</span><span class="o">.</span><span class="n">gpkg</span>
<span class="n">Layer</span> <span class="n">name</span><span class="p">:</span> <span class="n">SELECT</span>
<span class="n">Geometry</span><span class="p">:</span> <span class="n">Unknown</span> <span class="p">(</span><span class="nb">any</span><span class="p">)</span>
<span class="n">Feature</span> <span class="n">Count</span><span class="p">:</span> <span class="mi">1</span>
<span class="n">Layer</span> <span class="n">SRS</span> <span class="n">WKT</span><span class="p">:</span>
<span class="p">(</span><span class="n">unknown</span><span class="p">)</span>
<span class="n">HasSpatialIndex</span><span class="p">:</span> <span class="n">Integer</span> <span class="p">(</span><span class="mf">0.0</span><span class="p">)</span>
<span class="n">OGRFeature</span><span class="p">(</span><span class="n">SELECT</span><span class="p">):</span><span class="mi">0</span>
<span class="n">HasSpatialIndex</span> <span class="p">(</span><span class="n">Integer</span><span class="p">)</span> <span class="o">=</span> <span class="mi">1</span>
</pre></div>
</div>
<p>and then add a spatial index with ogrinfo :</p>
<div class="highlight-default notranslate"><div class="highlight"><pre><span></span><span class="n">ogrinfo</span> <span class="o">-</span><span class="n">sql</span> <span class="s2">"SELECT CreateSpatialIndex('parcelle_graphique', 'geom')"</span> <span class="n">PARCELLES_GRAPHIQUES</span><span class="o">.</span><span class="n">gpkg</span>
</pre></div>
</div>
</section>
</section>
<section id="for-wfs-services-prevent-using-default-full-extent">
<h3><a class="toc-backref" href="#table-of-contents" role="doc-backlink">For WFS services, prevent using default/full extent</a><a class="headerlink" href="#for-wfs-services-prevent-using-default-full-extent" title="Link to this heading">¶</a></h3>
<p>For your database connections, MapServer may (by default) use the full
extents of your data while performing a query (which can cause slow responses
>30seconds). You should likely set the following layer METADATA to
disable this:</p>
<div class="highlight-mapfile notranslate"><div class="highlight"><pre><span></span><span class="k">METADATA</span>
<span class="s">"wfs_use_default_extent_for_getfeature"</span> <span class="s">"false"</span>
<span class="k">END</span>
</pre></div>
</div>
<p>Here is a fully enhanced layer example:</p>
<div class="highlight-mapfile notranslate"><div class="highlight"><pre><span></span><span class="k">LAYER</span>
<span class="k">NAME</span> <span class="s">"CLUS"</span>
<span class="k">METADATA</span>
<span class="s">"ows_title"</span> <span class="s">"CLUS"</span>
<span class="s">"ows_srs"</span> <span class="s">"EPSG:3857 EPSG:4326 EPSG:2154"</span>
<span class="s">"wfs_getfeature_formatlist"</span> <span class="s">"geojson"</span>
<span class="s">"wfs_geomtype"</span> <span class="s">"MultiPolygon"</span>
<span class="s">"gml_featureid"</span> <span class="s">"fid"</span>
<span class="s">"gml_include_items"</span> <span class="s">"all"</span>
<span class="s">"gml_types"</span> <span class="s">"auto"</span>
<span class="s">"wfs_extent"</span> <span class="s">"115134 6049690 1242200 7108930"</span> <span class="c">#set to improve performance for all DB layers</span>
<span class="s">"wfs_use_default_extent_for_getfeature"</span> <span class="s">"false"</span> <span class="c">#set to improve performance for all DB layers</span>
<span class="s">"ows_enable_request"</span> <span class="s">"*"</span>
<span class="k">END</span> <span class="c">#metadata</span>
<span class="k">TYPE</span> <span class="nb">POLYGON</span>
<span class="k">CONNECTIONTYPE</span> <span class="nb">OGR</span>
<span class="k">CONNECTION</span> <span class="s">"C:/ms4w/apps/RPG_2-0_GPKG_LAMB93_FR-2019/PARCELLES_GRAPHIQUES.gpkg"</span>
<span class="k">DATA</span> <span class="s">"parcelle_graphique"</span>
<span class="k">EXTENT</span> <span class="mi">115134</span> <span class="mi">6049690</span> <span class="mi">1242200</span> <span class="mi">7108930</span> <span class="c">#set to improve performance for all DB layers</span>
<span class="k">PROCESSING</span> <span class="s">"CLOSE_CONNECTION=DEFER"</span> <span class="c">#set to improve performance for all DB layers</span>
<span class="k">STATUS</span> <span class="nb">ON</span>
<span class="k">PROJECTION</span>
<span class="s">"init=epsg:2154"</span>
<span class="k">END</span> <span class="c">#proj</span>
<span class="k">COMPOSITE</span>
<span class="k">OPACITY</span> <span class="mi">100</span>
<span class="k">END</span> <span class="c">#composite</span>
<span class="k">CLASS</span>
<span class="k">NAME</span> <span class="s">"CLUS"</span>
<span class="k">STYLE</span>
<span class="k">OUTLINECOLOR</span> <span class="mi">255</span> <span class="mi">0</span> <span class="mi">255</span>
<span class="k">END</span> <span class="c">#style</span>
<span class="k">END</span> <span class="c">#class</span>
<span class="k">END</span> <span class="c">#layer</span>
</pre></div>
</div>
</section>
</section>
</section>
<div class="clearer"></div>
</div>
</div>
</div>
<div class="sphinxsidebar" role="navigation" aria-label="Main">
<div class="sphinxsidebarwrapper">
<search id="searchbox" style="display: none" role="search">
<h3 id="searchlabel">Quick search</h3>
<div class="searchformwrapper">
<form class="search" action="../search.html" method="get">
<input type="text" name="q" aria-labelledby="searchlabel" autocomplete="off" autocorrect="off" autocapitalize="off" spellcheck="false"/>
<input type="submit" value="Go" />
</form>
</div>
</search>
<script>document.getElementById('searchbox').style.display = "block"</script><h3>Navigation</h3>
<p>
<a href="../about.html" title="About">About</a><br>
<a href="../products.html" title="Products">Products</a><br>
<a href="../community/index.html" title="Community">Community</a><br>
<a href="../development/index.html" title="Development">Development</a><br>
<a href="../download.html" title="Downloads">Downloads</a><br>
<a href="../documentation.html" title="Documentation">Documentation</a><br>
<a href="../faq.html" title="FAQ">FAQ</a><br>
<a href="../psc.html" title="PSC">PSC</a><br>
<a href="https://fosstodon.org/@mapserver" title="Mastodon">Mastodon</a>
</p>
<h3>Current Table Of Contents</h3>
<ul>
<li><a class="reference internal" href="#">Vector Data Management & Optimization</a><ul>
<li><a class="reference internal" href="#choose-the-right-vector-format-for-your-needs">Choose the right vector format for your needs</a></li>
<li><a class="reference internal" href="#spend-time-to-review-gdal-s-associated-driver-page-for-your-chosen-format">Spend time to review GDAL’s associated driver page for your chosen format</a></li>
<li><a class="reference internal" href="#connect-to-your-data-through-ogr-gdal">Connect to your data through OGR/GDAL</a></li>
<li><a class="reference internal" href="#learn-review-the-various-ogr-utilities-to-manage-your-vectors">Learn & Review the various OGR utilities to manage your vectors</a></li>
<li><a class="reference internal" href="#index-your-data">Index your data</a><ul>
<li><a class="reference internal" href="#tileindexing">Tileindexing</a></li>
<li><a class="reference internal" href="#add-a-spatial-index-to-your-data">Add a Spatial Index to your data</a></li>
<li><a class="reference internal" href="#add-an-attribute-index-to-your-data">Add an Attribute Index to your data</a></li>
</ul>
</li>
<li><a class="reference internal" href="#splitting-your-data">Splitting your data</a></li>
<li><a class="reference internal" href="#handling-your-vector-layers-in-the-mapfile">Handling your vector LAYERS in the mapfile</a></li>
<li><a class="reference internal" href="#shapefile-notes">Shapefile Notes</a></li>
<li><a class="reference internal" href="#postgis-notes">PostGIS Notes</a><ul>
<li><a class="reference internal" href="#indexing-with-postgis">Indexing with PostGIS</a></li>
<li><a class="reference internal" href="#specifying-a-unique-id-column">Specifying a Unique ID column</a></li>
<li><a class="reference internal" href="#debugging-speed-issues-with-postgis">Debugging speed issues with PostGIS</a></li>
</ul>
</li>
<li><a class="reference internal" href="#databases-in-general-postgis-oracle-spatialite-geopackage-microsoft-sql-server-mysql">Databases in General (PostGIS, Oracle, SpatiaLite, GeoPackage, Microsoft SQL Server, MySQL)</a><ul>
<li><a class="reference internal" href="#enable-connection-pooling">Enable Connection Pooling</a></li>
<li><a class="reference internal" href="#set-extent-at-the-layer-level-of-mapfile">Set EXTENT at the LAYER level of mapfile</a></li>
<li><a class="reference internal" href="#verify-that-your-table-has-a-spatial-index">Verify that your table has a Spatial Index</a><ul>
<li><a class="reference internal" href="#postgresql-postgis-example">PostgreSQL/PostGIS example</a></li>
<li><a class="reference internal" href="#geopackage-example">GeoPackage example</a></li>
</ul>
</li>
<li><a class="reference internal" href="#for-wfs-services-prevent-using-default-full-extent">For WFS services, prevent using default/full extent</a></li>
</ul>
</li>
</ul>
</li>
</ul>
</div>
</div>
<div class="clearer"></div>
</div>
<div class="related" role="navigation" aria-label="Related">
<h3>Navigation</h3>
<ul>
<li class="right" style="margin-right: 10px">
<a href="../genindex.html" title="General Index"
>index</a></li>
<li class="right" >
<a href="../utilities/index.html" title="Utilities"
>next</a> |</li>
<li class="right" >
<a href="tileindex.html" title="Tile Indexes"
>previous</a> |</li>
<li class="nav-item nav-item-0"><a href="../index.html">Home</a> »</li>
<li class="nav-item nav-item-1"><a href="../documentation.html" >MapServer 8.6.1 Documentation</a> »</li>
<li class="nav-item nav-item-2"><a href="index.html" >Optimization</a> »</li>
<li class="nav-item nav-item-this"><a href="">Vector Data Management & Optimization</a></li>
</ul>
</div>
<div class="footer" role="contentinfo">
© <a href="../copyright.html">Copyright</a> 2026, Open Source Geospatial Foundation.
Last updated on 2026-03-30.
Created using <a href="https://www.sphinx-doc.org/">Sphinx</a> 9.1.0.
</div>
</body>
</html>