官术网_书友最值得收藏!

  • QGIS 2 Cookbook
  • Alex Mandel Víctor Olaya Ferrero Anita Graser Alexander Bruy
  • 778字
  • 2021-07-16 11:12:41

Creating spatial indexes

Spatial indexes are methods to speed up queries of geometries. This includes speeding up the display of database layers in QGIS when you zoom in close (it has no effect on viewing entire layers).

This recipe applies to SpatiaLite and PostGIS databases. In the event that you've made a new table or you have imported some data and didn't create a spatial index, it's usually a good idea to add this.

Tip

You can also create a spatial index for shapefile layers. Take a look at Layer Properties | General for the Create Spatial Index button. This will create a .qix file that works with QGIS, Mapserver, GDAL/OGR, and other open source applications. Refer to https://en.wikipedia.org/wiki/Shapefile.

Getting ready

You'll need a SpatiaLite and a Postgis database. For ease, import a vector layer from the provided sample data and do not select the Create spatial index option when importing. (Not sure how to import data? Refer to Chapter 1, Data Input and Output, for how to do this.)

How to do it…

Using the DB Manager plugin (in the Database menu), perform the following steps:

  1. Check whether the index does not exist. In DB Manager, open the database and then open the table that you want to check. Looking at the properties on the right, you should see a message just above Fields that looks like this:
    How to do it…
  2. However, what if no index was listed for the geom column? Then, we can make one just by clicking the create it link. Or you can do this in a SQL window, as follows:
    • For SpatiaLite, use the following:
      SELECT CreateSpatialIndex('schools_wake', 'geom');
    • For PostGIS, use the following:
      CREATE INDEX sidx_census_wake2000_geom
        ON public.census_wake2000 USING gist(geom);
  3. Verify that the index exists, as follows:
    • For PostGIS (the left-hand side of the following screenshot), on the right-hand side, scroll to the bottom looking for the Indexes section
    • For SpatiaLite (the right-hand side of the following screenshot), you can see the idx_nameoftable_geomcolumn listed as a table:
    How to do it…

How it works…

When you create a spatial index, the database stores a bounding box rectangle for every spatial object in the geometry column. These boxes are also sorted so that boxes near each other in coordinate space are also near each other in the index.

When queries are run involving a location, a comparison is made against the boxes, which is a simple math comparison. Rows with boxes that match the area in question are then selected to be tested in depth for a precise match, based on their real geometries. This method of searching for intersection is faster than testing complex geometries one by one because it quickly eliminates items that are clearly not near the area of interest.

There's more…

Spatial indexes are really important to speed up the loading time of database spatial layers in QGIS. They also play a critical role in the speed of spatial queries (such as intersects). Note that PostGIS will automatically use a spatial index if one is present. SpatiaLite requires that you write queries that intentionally call a particular spatial index (Refer to Haute Cuisine examples from the SpatiaLite Cookbook)

Also, keep in mind that only one spatial index per table can be used in a single query. This really comes into play if you happen to have more than one spatial column or create a spatial index in a different projection than the geometry (check out the PostGIS Cookbook by Packt Publishing for more information).

Tip

If you plan to insert many records into a table with an existing spatial index, you may want to disable or drop the index and recreate it after the import is done. Otherwise, the index will be recalculated after each row is inserted. This applies to nonspatial indexes too.

Do you want to check lots of tables at once? You can list all GIST indexes in PostGIS at once:

SELECT i.relname as indexname, idx.indrelid::regclass as tablename,
  am.amname as typename,
ARRAY(SELECT pg_get_indexdef(idx.indexrelid, k + 1, true)
  FROM generate_subscripts(idx.indkey, 1) as k
  ORDER BY k
  ) as indkey_names
FROM pg_index as idx
JOIN pg_class as i  ON  i.oid = idx.indexrelid
JOIN pg_am as am  ON  i.relam = am.oid
JOIN pg_namespace as ns  ON  ns.oid = i.relnamespace
AND ns.nspname = ANY(current_schemas(false))
Where am.amname Like 'gist';

To do something similar in SpatiaLite, use the following:

SELECT * FROM geometry_columns WHERE spatial_index_enabled = 1;

See also

主站蜘蛛池模板: 婺源县| 盐池县| 如东县| 南通市| 周口市| 洛浦县| 三江| 苏州市| 咸阳市| 安图县| 东阿县| 广元市| 合水县| 保山市| 聂拉木县| 利川市| 沧源| 青岛市| 祁门县| 奉新县| 许昌市| 东乌珠穆沁旗| 礼泉县| 江陵县| 保靖县| 洛隆县| 平南县| 珠海市| 开封县| 武川县| 大宁县| 靖远县| 台南县| 宁南县| 孟津县| 西安市| 泉州市| 鄢陵县| 丽江市| 肥乡县| 潢川县|