PostGIS Layers

提供: OSGeo.JP Wiki
2009年8月17日 (月) 10:20時点におけるKayama (トーク | 投稿記録)による版

移動: 案内検索

PostGIS Layers

<A NAME="886"></A> <A NAME="107"></A> <A NAME="label_postgis"></A>

PostGIS layers are stored in a PostgreSQL database. The advantages of PostGIS are the spatial indexing, filtering and query capabilities it provides. Using PostGIS, vector functions such as select and identify work more accurately than with OGR layers in QGIS. <P> To use PostGIS layers you must:<A NAME="109"></A> <P>

  • Create a stored connection in QGIS to the PostgreSQL database (if one is not already defined).<A NAME="111"></A>
  • Connect to the database.
  • Select the layer to add to the map.
  • Optionally provide a SQL where clause to define which features to load from the layer.
  • Load the layer.

<P>



Creating a stored Connection

<P> [width=0.7cm]mActionAddLayer The first time you use a PostGIS data source, you must create a connection to the PostgreSQL database that contains the data. Begin by clicking on the mActionAddLayerAdd a PostGIS Layer toolbar button, selecting the mActionAddLayerAdd a PostGIS Layer... option from the Layer menu or typing D. You can also open the open the Add Vector Layer dialog and select Database. The Add PostGIS Table(s) dialog will be displayed. To access the connection manager<A NAME="127"></A>, click on the New button to display the Create a New PostGIS Connection dialog. The parameters required for a connection are shown in table <A HREF="#tab:postgis_connection_parms">1</A>.

<P>


<P>


<A NAME="tab:postgis_connection_parms"></A>


Table 1: PostGIS Connection Parameters
Name A name for this connection. Can be the same as Database.
Host <A NAME="138"></A> Name of the database host. This must be a resolvable host name the same as

would be used to open a telnet connection or ping the host. If the database is

on the same computer as QGIS, simply enter 'localhost' here.
Database <A NAME="139"></A> Name of the database.
Port <A NAME="140"></A> Port number the PostgreSQL database server listens on. The default port is 5432.
Username <A NAME="141"></A> User name used to login to the database.
Password <A NAME="142"></A> Password used with Username to connect to the database.
SSL mode <A NAME="144"></A> How the SSL connection will be negotiated with the server. These are the options:
  • disable: only try an unencrypted SSL connection;
  • allow: try a non-SSL connection, if that fails, try an SSL connection;
  • prefer (the default): try an SSL connection, if that fails, try a non-SSL connection;
  • require: only try an SSL connection.
Note that massive speedups in PostGIS layer rendering can be achieved by disabling SSL in the connection editor.

</DIV>
</DIV>

<P> Optional you can activate follwing checkboxes:

<P>

  • Save Password
  • Only look in the geometry_columns table
  • Only look in the 'public' schema

<P> Once all parameters and options are set, you can test the connection by clicking on the Test Connect button<A NAME="155"></A>.

<P>



Loading a PostGIS Layer

<P> [width=0.7cm]mActionAddLayer Once you have one or more connections defined, you can load layers from the PostgreSQL database. Of course this requires having data in PostgreSQL. See Section <A HREF="node11.html#sec:loading_postgis_data">5.2.4</A> for a discussion on importing data into the database.

<P> To load a layer from PostGIS, perform the following steps:

<P>

  • If the Add PostGIS Table(s) dialog is not already open, click on the mActionAddLayerAdd a PostGIS Layer toolbar button.
  • Choose the connection from the drop-down list and click Connect.
  • Find the layer you wish to add in the list of available layers.
  • Select it by clicking on it. You can select multiple layers by holding down the shift key while clicking. See Section <A HREF="node29.html#sec:query_builder">5.6</A> for information on using the PostgreSQL Query Builder to further define the layer.
  • Click on the Add button to add the layer to the map.

<P>


Some details about PostgreSQL layers

<P> This section contains some details on how QGIS accesses PostgreSQL layers. Most of the time QGIS should simply provide you with a list of database tables that can be loaded, and load them on request. However, if you have trouble loading a PostgreSQL table into QGIS, the information below may help you understand any QGIS messages and give you direction on changing the PostgreSQL table or view definition to allow QGIS to load it.

<P> QGIS requires that PostgreSQL layers contain a column that can be used as a unique key for the layer. For tables this usually means that the table needs a primary key, or a column with a unique constraint on it. In QGIS, this column needs to be of type int4 (an integer of size 4 bytes). Alternatively the ctid column can be used as primary key. If a table lacks these items, the oid column will be used instead. Performance will be improved if the column is indexed (note that primary keys are automatically indexed in PostgreSQL).

<P> If the PostgreSQL layer is a view, the same requirement exists, but views don't have primary keys or columns with unique constraints on them. In this case QGIS will try to find a column in the view that is derived from a suitable table column. It does this by parsing the view definition SQL. However there are several aspects of SQL that QGIS ignores - these include the use of table aliases and columns that are generated by SQL functions.

<P> If a suitable column cannot be found, QGIS will not load the layer. If this occurs, the solution is to alter the view so that it does include a suitable column (a type of int4 and either a primary key or with a unique constraint, preferably indexed).

<P> When dealing with views, QGIS parses the view definition and


Importing Data into PostgreSQL

<P> shp2pgsql Data can be imported into PostgreSQL using a number of methods. PostGIS includes a utility called shp2pgsql that can be used to import shapefiles into a PostGIS enabled database. For example, to import a shapefile named lakes.shp into a PostgreSQL database named gis_data, use the following command:

<P>

 
  shp2pgsql -s 2964 lakes.shp lakes_new | psql gis_data

<P> This creates a new layer named lakes_new in the gis_data database. The new layer will have a spatial reference identifier (SRID) of 2964. See Section <A HREF="#label_projections"><IMG ALIGN="BOTTOM" BORDER="1" ALT="[*]"

SRC="/usr/share/latex2html/icons/crossref.png"></A> for more information on spatial reference systems and

projections.
<IMG

WIDTH="128" HEIGHT="11" ALIGN="BOTTOM" BORDER="0"
SRC="img7.png"
ALT="\begin{Tip}

% latex2html id marker 194\caption{\textsc{Exporting datasets from... ...lename{pgsql2shp}. This is shipped within your PostGIS distribution.} \end{Tip}">

<P> SPIT Plugin [width=0.7cm]spiticon QGIS comes with a plugin named SPIT (Shapefile to PostGIS Import Tool)<A NAME="202"></A>. SPIT can be used to load multiple shapefiles at one time and includes support for schemas. To use SPIT, open the Plugin Manager from the Plugins menu, check the box next to the SPIT plugin and click OK. The SPIT icon will be added to the plugin toolbar<A NAME="206"></A>.

<P> To import a shapefile, click on the spiticonSPIT tool in the toolbar to open the SPIT - Shapefile to PostGIS Import Tool dialog. Select the PostGIS database you want to connect to and click on Connect. Now you can add one or more files to the queue by clicking on the Add button. To process the files, click on the OK button. The progress of the import as well as any errors/warnings will be displayed as each shapefile is processed.

<P>


<P> ogr2ogr Beside shp2pgsql and SPIT there is another tool for feeding geodata in PostGIS: ogr2ogr. This is part of your GDAL installation. To import a shapefile into PostGIS, do the following:

  ogr2ogr -f "PostgreSQL" PG:"dbname=postgis host=myhost.de user=postgres \
  password=topsecret" alaska.shp

<P> This will import the shapefile alaska.shp into the PostGIS-database postgis using the user postgres with the password topsecret on host myhost.de.

<P> Note that OGR must be built with PostgreSQL to support PostGIS. You can see this by typing

ogrinfo --formats | grep -i post

<P> If you like to use PostgreSQL's COPY-command instead of the default INSERT INTO method you can export the following environment-variable (at least available on and ):

  export PG_USE_COPY=YES

<P> ogr2ogr does not create spatial indexes like shp2pgsl does. You need to create them manually using the normal SQL-command CREATE INDEX afterwards as an extra step (as described in the next section <A HREF="node12.html#label_improve">5.2.5</A>).

<P>

Improving Performance

<P> Retrieving features from a PostgreSQL database can be time consuming, especially over a network. You can improve the drawing performance of PostgreSQL layers by ensuring that a <A NAME="241"></A> spatial index exists on each layer in the database. PostGIS supports creation of a <A NAME="242"></A> GiST (Generalized Search Tree) index to speed up spatial searches of the data.

<P> The syntax for creating a GiST<A NAME="tex2html48"

 HREF="footnode.html#foot895"><IMG  ALIGN="BOTTOM" BORDER="1" ALT="[*]"
SRC="/usr/share/latex2html/icons/footnote.png"></A>index is:

<P>

    CREATE INDEX [indexname] ON [tablename] 
      USING GIST ( [geometryfield] GIST_GEOMETRY_OPS );

<P> Note that for large tables, creating the index can take a long time. Once the index is created, you should perform a VACUUM ANALYZE. See the PostGIS documentation [#!PostGISweb!#] for more information.

<P> The following is an example of creating a GiST index:

gsherman@madison:~/current$ psql gis_data
Welcome to psql 8.3.0, the PostgreSQL interactive terminal.

Type:  \copyright for distribution terms
        \h for help with SQL commands
        \? for help with psql commands
        \g or terminate with semicolon to execute query
        \q to quit

gis_data=# CREATE INDEX sidx_alaska_lakes ON alaska_lakes
gis_data-# USING GIST (the_geom GIST_GEOMETRY_OPS);
CREATE INDEX
gis_data=# VACUUM ANALYZE alaska_lakes;
VACUUM
gis_data=# \q
gsherman@madison:~/current$

<P>




Vector layers crossing 180 longitude

<P> Many GIS packages don't wrap vector maps, with a geographic reference system (lat/lon), crossing the 180 longitude line. As result, if we open such map in QGIS, we will see two far, distinct locations, that should show near each other. In Figure <A HREF="#fig:vector_not_wrapping">8</A> the tiny point on the far left of the map canvas (Chatham Islands), should be within the grid, right of New Zealand main islands.

<P>

<A NAME="fig:vector_not_wrapping"></A><A NAME="896"></A>
Figure: Map in lat/lon crossing the 180 longitude line

[clip=true, width=]vectorNotWrapping

<P> A workaround is to transform the longitude values using PostGIS and the STShiftLongitude <A NAME="tex2html54"

 HREF="footnode.html#foot897"><IMG  ALIGN="BOTTOM" BORDER="1" ALT="[*]"
SRC="/usr/share/latex2html/icons/footnote.png"></A>function. This function reads every point/vertex in every component of every

feature in a geometry, and if the longitude coordinate is < 0 adds 360 to it. The result would be a 0 - 360 version of the data to be plotted in a 180 centric map.

<P>

<A NAME="fig:vector_wrapping"></A><A NAME="898"></A>
Figure: Map crossing the 180 longitude line after applying the STShiftLongitude function

[clip=true, width=9cm]vectorWrapping

<P> Usage

<P>

  • Import data to PostGIS (<A HREF="node11.html#sec:loading_postgis_data">5.2.4</A>) using for example the PostGIS Manager plugin or the SPIT plugin
  • Use the PostGIS command line interface to issue the following command (this is an example where "TABLE" is the actual name of your PostGIS table)
    gis_data=# update TABLE set the_geom=ST_shift_longitude(the_geom);
  • If everything went right you should receive a confirmation about the number of features that were updated, then you'll be able to load the map and see the difference (Figure <A HREF="#fig:vector_wrapping">9</A>)
<P>