Go to the first, previous, next, last section, table of contents.


10 Spatial Extensions in MySQL

In release 4.1 MySQL introduces spatial extensions, which allow generation, storage and analysis of geographic features. This chapter describes:

10.1 Introduction

This section describes what geographic features are and the general approach that MySQL takes for representing them.

10.1.1 Geographic Features

A geographic feature is anything in the world that has a location.

A feature can be:

You can also find documents that use term geospatial feature to refer to geographic features.

Geometry is another word that denotes a geographic feature. The original meaning of the word geometry denotes a branch of mathematics. Another meaning that comes from cartography, referring to the geometric features that cartographers use to map the world.

We will mean the same thing using all these terms, a geographic feature, or a geospatial feature, or a feature, or a geometry, with geometry as the most used in this documentation.

Let's define a geometry as a point or an aggregate of points representing anything in the world that has a location.

10.1.2 MySQL's Approach to Representing Spatial Data

MySQL implements spatial extensions following Open GIS specifications.

The Open GIS Consortium (OGC), is an international consortium of more than 250 companies, agencies, universities participating in the development of publicly available conceptual solutions that can be useful with all kinds of applications that manage spatial data. See http://www.opengis.org/.

In 1997, the Open GIS Consortium published the OpenGIS (r) Simple Features Specifications For SQL, which proposes several conceptual ways for extending an SQL RDBMS to support spatial data. MySQL implements a subset of the SQL with Geometry Types environment proposed by OGC. This term refers to an SQL environment that has been extended with a set of geometry types. A geometry-valued SQL column is implemented as a column that has a geometry type. The specifications describe a set of SQL geometry types, as well as functions on those types to create and analyse geometry values.

10.2 The OpenGIS Geometry Model

The set of geometry types proposed by OGC's SQL with Geometry Types environment is based on the OpenGIS Geometry Model. In this model, each geometric object has the following general properties:

10.2.1 The Geometry Class Hierarchy

The geometry classes define a hierarchy. Each class has properties and may have assertions (rules that define valid class instances). The class hierarchy is as follows:

Some of these classes are abstract (non-instantiable). That is, it is not possible to create an object of these classes. Other classes are instantiable and objects may be created of them.

Geometry is the base class. It's an abstract class. The instantiable subclasses of Geometry are restricted to zero-, one-, and two-dimensional geometric objects that exist in two-dimensional coordinate space. All instantiable geometry classes are defined so that valid instances of a geometry class are topologically closed (that is, all defined geometries include their boundary).

The base Geometry class has subclasses for Point, Curve, Surface and GeometryCollection.

Point stands for zero-dimensional objects.

Curve stands for one-dimensional objects, and has subclass LineString, with sub-subclasses Line and LinearRing.

Surface is designed for two-dimensional objects and has subclass Polygon.

GeometryCollection has specialised zero-, one-, and two-dimensional collection classes named MultiPoint, MultiLineString, and MultiPolygon for modelling geometries corresponding to collections of Points, LineStrings, and Polygons, respectively. MultiCurve and MultiSurface are introduced as abstract superclasses that generalise the collection interfaces to handle Curves and Surfaces.

Geometry, Curve, Surface, MultiCurve, and MultiSurface are defined as non-instantiable classes. They define a common set of methods for their subclasses and are included for the reason of extensibility.

Point, LineString, Polygon, GeometryCollection, MultiPoint, MultiLineString, and MultiPolygon are instantiable classes.

10.2.2 Class Geometry

Geometry is the root class of the hierarchy. Each geometry is described by a number of its properties. Particular subclasses of the root class Geometry have their own specific properties. Properties that are common for all geometry subclasses, are described in the list below. Geometry is a non-instantiable class.

10.2.3 Geometry properties

A geometry value has the following properties:

Coordinates are related to the SRID. For example, in different coordinate systems, the distance between two objects may differ even when objects have the same coordinates, because the distance on the planar coordinate system and the distance on the geocentric system (coordinates on the Earth's surface) are different things.

10.2.4 Class Point

A Point is a geometry that represents a single location in coordinate space.

10.2.5 Point Examples

10.2.6 Point Properties

10.2.7 Class Curve

A Curve is a one-dimensional geometry, usually represented by a sequence of points. Particular subclasses of Curve specify the form of the interpolation between points. Curve is a non-instantiable class.

10.2.8 Curve Properties

10.2.9 Class LineString

A LineString is a Curve with linear interpolation between points.

10.2.10 LineString Examples

10.2.11 LineString Properties

10.2.12 Class Surface

A Surface is a two-dimensional geometric object.

10.2.13 Surface Properties

The only instantiable subclass of Surface defined in the OpenGIS specification is Polygon.

10.2.14 Class Polygon

A Polygon is a planar Surface representing a multisided geometry, defined by one exterior boundary and zero or more interior boundaries. Each interior boundary defines a hole in the Polygon.

10.2.15 Polygon Examples

10.2.16 Polygon Assertions

In the above assertions, polygons are simple geometries.

10.2.17 Class GeometryCollection

A GeometryCollection is a geometry that is a collection of one or more geometries of any class.

All the elements in a GeometryCollection must be in the same Spatial Reference (that is, in the same coordinate system). GeometryCollection places no other constraints on its elements.

Subclasses of GeometryCollection described below may restrict membership based on:

10.2.18 Class MultiPoint

A MultiPoint is a collection whose elements are restricted to Point objects. The points are not connected or ordered in any way.

10.2.19 MultiPoint Examples

10.2.20 MultiPoint Properties

10.2.21 Class MultiCurve

A MultiCurve is a geometry collection whose elements are Curve values. MultiCurve is a non-instantiable class.

10.2.22 MultiCurve Properties

10.2.23 Class MultiLineString

A MultiLineString is a MultiCurve whose elements are LineString values.

10.2.24 MultiLineString Examples

10.2.25 Class MultiSurface

A MultiSurface is a geometric collection whose elements are surfaces. MultiSurface is a non-instantiable class.

10.2.26 MultiSurface Assertions

The only instantiable subclass of MultiSurface is MultiPolygon.

10.2.27 Class MultiPolygon

A MultiPolygon is a MultiSurface whose elements are Polygon values.

10.2.28 MultiPolygon Examples

10.2.29 MultiPolygon Assertions

10.2.30 MultiPolygon Properties

10.3 Supported Spatial Data Formats

This section describes the standard spatial data formats that are used to represent geometry objects in queries. They are:

Internally, MySQL stores geometry values in a format that is not identical to either WKT or WKB format.

10.3.1 Well-Known Text (WKT) Representation

The Well-Known Text (WKT) representation of Geometry is designed to exchange geometry data in ASCII form.

Examples of WKT representations of geometry objects are:

A Backus-Naur grammer that specifies the formal production rules for writing WKT values may be found in the OGC specification document referenced near the beginning of this chapter.

10.3.2 Well-Known Binary (WKB) Representation

The well-Known Binary (WKB) representation for geometric values is defined by the OpenGIS specifications. It's also defined in the ISO ``SQL/MM Part 3: Spatial'' standard.

WKB is used to exchange geometry data as binary streams represented by BLOB values containing geometric WKB information. The basic WKB type definitions use the structures shown in the following sections.

10.3.2.1 WKB Basic Types

// byte   : 8-bit unsigned integer (1 byte)
// uint32 : 32-bit unsigned integer (4 bytes)
// double : double precision number (8 bytes)

enum wkbGeometryType
{
    wkbPoint              = 1,
    wkbLineString         = 2,
    wkbPolygon            = 3,
    wkbMultiPoint         = 4,
    wkbMultiLineString    = 5,
    wkbMultiPolygon       = 6,
    wkbGeometryCollection = 7
}

enum wkbByteOrder
{
    wkbXDR = 0,    // Big Endian
    wkbNDR = 1     // Little Endian
}

10.3.2.2 WKB Building Blocks

// Building Blocks : Point, LinearRing

Point
{
    double  x;
    double  y;
}

LinearRing
{
    uint32  numPoints;
    Point   points[numPoints];
}

10.3.2.3 WKB Representation of Geometry Values

WKBPoint
{
    byte    byteOrder;
    uint32  wkbType;     // 1
    Point   point;
}

WKBLineString
{
    byte    byteOrder;
    uint32  wkbType;     // 2
    uint32  numPoints;
    Point   points[numPoints];
}

WKBPolygon
{
    byte       byteOrder;
    uint32     wkbType;  // 3
    uint32     numRings;
    LinearRing rings[numRings];
}

WKBMultiPoint
{
    byte       byteOrder;
    uint32     wkbType;  // 4
    uint32     num_wkbPoints;
    WKBPoint   WKBPoints[num_wkbPoints];
}

WKBMultiLineString
{
    byte          byteOrder;
    uint32        wkbType;    // 5
    uint32        num_wkbLineStrings;
    WKBLineString WKBLineStrings[num_wkbLineStrings];
}

wkbMultiPolygon
{
    byte       byteOrder;
    uint32     wkbType;    // 6
    uint32     num_wkbPolygons;
    WKBPolygon wkbPolygons[num_wkbPolygons];
}

WKBGeometry
{
    union
    {
        WKBPoint            point;
        WKBLineString       linestring;
        WKBPolygon          polygon;
        WKBGeometryCollection collection;
        WKBMultiPoint       mpoint;
        WKBMultiLineString  mlinestring;
        WKBMultiPolygon     mpolygon;
    }
}

WKBGeometryCollection
{
    byte        byte_order;
    uint32      wkbType;    // 7
    uint32      num_wkbGeometries;
    WKBGeometry wkbGeometries[num_wkbGeometries];
}

10.3.2.4 WKB Examples

A WKB that corresponds to POINT(1,1) has this sequence of 21 bytes (each represented by two hex digits):

0101000000000000000000F03F000000000000F03F

The sequence may be broken down into the following components:

Byte order : 01
WKB type   : 01000000
X          : 000000000000F03F
Y          : 000000000000F03F

10.4 Creating a Spatially-Enabled MySQL Database

10.4.1 MySQL Spatial Data Types

MySQL provides a set of datatypes that correspond to classes in the class hierarchy of the OpenGIS Geometry Model:

GEOMETRY is the most general of these types; it can store geometry values of any type. Other types restrict their values to a particular geometry type. GEOMETRYCOLLECTION can store a collection of objects of any type. Other collection types (those beginning with MULTI) restrict collection members to those having a particular geometry type.

10.4.2 Creating Spatial Values

This section describes how to create spatial values using Well-Known Text and Well-Known Binary functions that are defined in the OpenGIS standard, and using MySQL-specific functions.

10.4.2.1 Creating Geometry Values Using WKT Functions

MySQL provides a number of functions that take as input parameters a Well-Known Text representation and, optionally, a spatial reference system identifier (SRID), and return the corresponding geometry.

GeomFromText() accepts a WKT of any geometry type as its first argument. For construction of geometry values restricted to a particular type, an implementation also provides a type-specific construction function for each geometry type.

GeomFromText(wkt,srid)
GeometryFromText(wkt,srid)
Constructs a geometry of any type using its WKT representation and SRID.
PointFromText(wkt,srid)
Constructs a POINT using its WKT representation and SRID.
LineFromText(wkt,srid)
LineStringFromText(wkt,srid)
Constructs a LINESTRING using its WKT representation and SRID.
PolyFromText(wkt,srid)
PolygonFromText(wkt,srid)
Constructs a POLYGON using its WKT representation and SRID.
MPointFromText(wkt,srid)
MultiPointFromText(wkt,srid)
Constructs a MULTIPOINT using its WKT representation and SRID.
MLineFromText(wkt,srid)
MultiLineStringFromText(wkt,srid)
Constructs a MULTILINESTRING using its WKT representation and SRID.
MPolyFromText(wkt,srid)
MultiPolygonFromText(wkt,srid)
Constructs a MULTIPOLYGON using its WKT representation and SRID.
GeomCollFromText(wkt,srid)
GeometryCollectionFromText(wkt,srid)
Constructs a GEOMETRYCOLLECTION using its WKT representation and SRID.

As an optional feature, an implementation may also support building of Polygon or MultiPolygon values, given an arbitrary collection of possibly intersecting rings or closed LineString values. Implementations that support this feature should include the following functions (Note: MySQL does not yet implement these):

BdPolyFromText(multiLineStringTaggedText String, SRID Integer):Polygon
Given an arbitrary collection of closed LineString values, constructs a Polygon as a MultiLineString text representation.
BdMPolyFromText(multiLineStringTaggedText String, SRID Integer):MultiPolygon
Given an arbitrary collection of closed LineString values, constructs a MultiPolygon as a MultiLineString text representation.

10.4.2.2 Creating Geometry Values Using WKB Functions

MySQL provides a number of of functions that take as input parameters a BLOB containing a Well-Known Binary representation and, optionally, a spatial reference system identifier (SRID), and return the corresponding geometry.

GeomFromWKB() accepts a WKB of any geometry type as its first argument. For construction of geometry values restricted to a particular type, an implementation also provides a specific construction function for each geometry type.

GeomFromWKB(wkb,srid)
GeometryFromWKB(wkt,srid)
Constructs a geometry of any type using its WKB representation and SRID.
PointFromWKB(wkb,srid)
Constructs a POINT using its WKB representation and SRID.
LineFromWKB(wkb,srid)
LineStringFromWKB(wkb,srid)
Constructs a LINESTRING using its WKB representation and SRID.
PolyFromWKB(wkb,srid)
PolygonFromWKB(wkb,srid)
Constructs a POLYGON using its WKB representation and SRID.
MPointFromWKB(wkb,srid)
MultiPointFromWKB(wkb,srid)
Constructs a MULTIPOINT using its WKB representation and SRID.
MLineFromWKB(wkb,srid)
MultiLineStringFromWKB(wkb,srid)
Constructs a MULTILINESTRING using its WKB representation and SRID.
MPolyFromWKB(wkb,srid)
MultiPolygonFromWKB(wkb,srid)
Constructs a MULTIPOLYGON using its WKB representation and SRID.
GeomCollFromWKB(wkb,srid)
GeometryCollectionFromWKB(wkt,srid)
Constructs a GEOMETRYCOLLECTION using its WKB representation and SRID.

As an optional feature, an implementation may also support the building of Polygon or MultiPolygon values given an arbitrary collection of possibly intersecting rings or closed LineString values. Implementations that support this feature should include the following functions (Note: MySQL does not yet implement these):

BdPolyFromWKB(WKBMultiLineString Binary,SRID Integer): Polygon
Constructs a Polygon given an arbitrary collection of closed linestrings as a MultiLineString binary representation.
BdMPolyFromWKB(WKBMultiLineString Binary, SRID Integer):MultiPolygon
Constructs a MultiPolygon given an arbitrary collection of closed linestrings as a MultiLineString binary representation.

10.4.2.3 Creating Geometry Values Using MySQL-Specific Functions

Note: MySQL does not yet implement the functions listed in this section.

MySQL provides a set of useful functions for creating geometry WKB representations. The functions described in this section are MySQL extensions to the OpenGIS specifications. The results of these functions are BLOB values containing geometry WKB representations (no SRID). The results of these functions can be substituted as the first argument for any function in the GeomFromWKB() function family.

Point(x,y)
Constructs a WKBPoint using its coordinates.
MultiPoint(WKBPoint,WKBPoint,...,WKBPoint)
Constructs a WKBMultiPoint using WKBPoint arguments. If any argument is not a WKBPoint, the return value is NULL.
LineString(WKBPoint,WKBPoint,...,WKBPoint)
Constructs a WKBLineString from a number of WKBPoint arguments. If any argument is not a WKBPoint, the return value is NULL. If the number of WKBPoint arguments is less than two, the return value is NULL.
MultiLineString(WKBLineString,WKBLineString,...,WKBLineString)
Constructs a WKBMultiLineString using using WKBLineString arguments. If any argument is not a WKBLineString, the return value is NULL.
Polygon(WKBLineString,WKBLineString,...,WKBLineString)
Constructs a Polygon from a number of WKBLineString arguments. If any argument is not representing WKB of a LinearRing (that is, not a closed and simple LineString) the return value is NULL.
MultiPolygon(WKBPolygon,WKBPolygon,...,WKBPolygon)
Constructs a WKBMultiPolygon from a set of WKBPolygon arguments. If any argument is not a WKBPolygon, the rerurn value is NULL.
GeometryCollection(WKBGeometry,WKBGeometry,..,WKBGeometry)
Constucts a GeometryCollection. If any argument is not a well-formed WKB representation of a geometry, the return value is NULL.

10.4.3 Creating Spatial Columns

MySQL provides a standard way of creating spatial columns for geometry types, for example, with CREATE TABLE or ALTER TABLE.

10.4.4 Populating Spatial Columns

After you have created spatial columns, you can populate them with your spatial data.

To populate spatially-enabled columns, MySQL supports two spatial formats (described previously), Well Known Text (WKT) and Well-Known Binary (WKB) representation.

10.4.4.1 Examples Of Using WKT Functions

INSERT INTO geom VALUES
    (GeomFromText('POINT(1 1)'));
INSERT INTO geom VALUES
    (GeomFromText('LINESTRING(0 0,1 1,2 2)'));
INSERT INTO geom VALUES
    (GeomFromText('POLYGON((0 0,10 0,10 10,0 10,0 0),(5 5,7 5,7 7,5 7, 5 5))'));
INSERT INTO geom VALUES
    (GeomFromText('GEOMETRYCOLLECTION(POINT(1 1),LINESTRING(0 0,1 1,2 2,3 3,4 4))'));
INSERT INTO geom VALUES
    (PointFromText('POINT(1 1)'));
INSERT INTO geom VALUES
    (LineStringFromText('LINESTRING(0 0,1 1,2 2)'));
INSERT INTO geom VALUES
    (PolygomFromText('POLYGON((0 0,10 0,10 10,0 10,0 0),(5 5,7 5,7 7,5 7, 5 5))'));
INSERT INTO geom VALUES
    (GeomCollFromText('GEOMETRYCOLLECTION(POINT(1 1),LINESTRING(0 0,1 1,2 2,3 3,4 4))'));

Note that if a client application program wants to use WKB representations of geometry values, it is responsible for sending correctly formed WKB in queries to the server. There are, however, several ways of satisfying this requirement. For example:

10.4.5 Fetching Spatial Data

Geometry values stored in a table can be fetched in either WKT or WKB representations.

10.4.5.1 Fetching Spatial Data Using WKT Representation

The AsText() function provides textual access to geometry values by converting each into a WKT string.

mysql> SELECT AsText(p1) FROM g1;
+-------------------------+
| AsText(p1)              |
+-------------------------+
| POINT(1 1)              |
| LINESTRING(0 0,1 1,2 2) |
+-------------------------+

10.4.5.2 Fetching Spatial Data Using WKB Representation

The AsBinary() function provides binary access to geometry values by converting each into its WKB representation and returning the BLOB containing the value.

SELECT AsBinary(g) FROM geom;

10.5 Analysing Spatial Information

After populating spatial columns with values, you are ready to query and analyse them. MySQL provides a set of functions to perform various operations on spatial data. These functions can be labeled into four major groups according to the type of operation they perform:

Spatial analysis functions can be used in many contexts, such as:

10.5.1 Functions To Convert Geometries Between Formats

MySQL supports the following functions for converting geometry values between internal format and either WKT or WKB format:

GeomFromText(string wkt [,integer srid]): geometry
Converts a value from its WKT representation into internal geometry format. A number of type-specific functions are also supported; see section 10.4.2.1 Creating Geometry Values Using WKT Functions.
GeomFromWKB(binary wkb [,integer srid]): geometry
Converts a value from its WKB representation into internal geometry format. A number of type-specific functions are also supported; see section 10.4.2.2 Creating Geometry Values Using WKB Functions.
AsText(geometry g): string
Converts a value from its internal geometry format into its WKT representation.
mysql> SELECT AsText(GeomFromText('LineString(1 1,2 2,3 3)'));
+-------------------------------------------------+
| AsText(GeomFromText('LineString(1 1,2 2,3 3)')) |
+-------------------------------------------------+
| LINESTRING(1 1,2 2,3 3)                         |
+-------------------------------------------------+
AsBinary(geometry g): binary
Converts a value from its internal geometry format into its WKB representation.

10.5.2 Functions To Analyse Geometry Properties

Functions that belong to this group take a geometry value as their argument and return some quantitive or qualitive property of this geometry. Some functions restrict their argument type. Such functions return NULL if the passed geometry is of an incorrect geometry type. For example, Area() returns NULL if the object type is neither Polygon nor MultiPolygon.

10.5.2.1 Basic Functions To Analyse Geometry Properties

These functions don't restrict their argument and accept a geometry value of any type.

GeometryType(geometry g):string
Returns as a string the name of the geometry subtype of which this geometry instance is a member.
mysql> SELECT GeometryType(GeomFromText('POINT(1 1)'));
+------------------------------------------+
| GeometryType(GeomFromText('POINT(1 1)')) |
+------------------------------------------+
| POINT                                    |
+------------------------------------------+
Dimension(geometry g):integer
The inherent dimension of this Geometry object, which can be -1, 0, 1 or 2. (The meaning of these values is given in section 10.2.2 Class Geometry.)
mysql> SELECT Dimension(GeomFromText('LineString(1 1,2 2)'));
+------------------------------------------------+
| Dimension(GeomFromText('LineString(1 1,2 2)')) |
+------------------------------------------------+
|                                              1 |
+------------------------------------------------+
SRID(geometry g):integer
Returns the Spatial Reference System ID for this geometry.
mysql> SELECT SRID(GeomFromText('LineString(1 1,2 2)',101));
+-----------------------------------------------+
| SRID(GeomFromText('LineString(1 1,2 2)',101)) |
+-----------------------------------------------+
|                                           101 |
+-----------------------------------------------+
Envelope(geometry g):geometry
The Minimum Bounding Rectangle (MBR) for this geometry, returned as a polygon. The polygon is defined by the corner points of the bounding box:
POLYGON((MINX MINY, MAXX MINY, MAXX MAXY, MINX MAXY, MINX MINY))
mysql> SELECT AsText(Envelope(GeomFromText('LineString(1 1,2 2)')));
+-------------------------------------------------------+
| AsText(Envelope(GeomFromText('LineString(1 1,2 2)'))) |
+-------------------------------------------------------+
| POLYGON((10.41032409668 1,1 2,1 2,2 1,2 1))           |
+-------------------------------------------------------+

Note: MySQL does not yet implement the following functions:

Boundary(g:Geometry):Geometry
Returns the closure of the combinatorial boundary of this Geometry.
IsEmpty(geometry g):Integer
Returns 1 (TRUE) if this Geometry is the empty geometry. If true, then this Geometry represents the empty point set.
IsSimple(geometry g):Integer
Returns 1 (TRUE) if this Geometry has no anomalous geometric points, such as self intersection or self tangency. The description of each instantiable geometric class includes the specific conditions that cause an instance of that class to be classified as not simple.

10.5.2.2 Functions To Analyse Point Properties

A Point consists of its X and Y coordinates, which may be obtained using the following functions:

X(point p):Double
The X-coordinate value for this point.
mysql> SELECT X(GeomFromText('Point(56.7 53.34)'));
+--------------------------------------+
| X(GeomFromText('Point(56.7 53.34)')) |
+--------------------------------------+
|                                 56.7 |
+--------------------------------------+
Y(point p):Double
The Y-coordinate value for this point.
mysql> SELECT Y(GeomFromText('Point(56.7 53.34)'));
+--------------------------------------+
| Y(GeomFromText('Point(56.7 53.34)')) |
+--------------------------------------+
|                                53.34 |
+--------------------------------------+

10.5.2.3 Functions To Analyse LineString Properties

A LineString consists of Point values. You can extract particular points, count the number of points, or obtain the length of a LineString.

EndPoint(LineString l):Point
The end point of this LineString.
mysql> SELECT AsText(EndPoint(GeomFromText('LineString(1 1,2 2,3 3)')));
+------------------------------------------------------------+
| AsText(EndPoint(GeomFromText('LineString(1 1,2 2,3 3)')))  |
+------------------------------------------------------------+
| POINT(3 3)                                                 |
+------------------------------------------------------------+
GLength(LineString l):Double
The length of this LineString in its associated spatial reference.
mysql> SELECT GLength(GeomFromText('LineString(1 1,2 2,3 3)'));
+--------------------------------------------------+
| GLength(GeomFromText('LineString(1 1,2 2,3 3)')) |
+--------------------------------------------------+
|                                  2.8284271247462 |
+--------------------------------------------------+
IsClosed(LineString l):Integer
Returns 1 (TRUE) if this LineString is closed (the StartPoint() and EndPoint() values are the same).
mysql> SELECT IsClosed(GeomFromText('LineString(1 1,2 2,3 3)'));
+---------------------------------------------------+
| IsClosed(GeomFromText('LineString(1 1,2 2,3 3)')) |
+---------------------------------------------------+
|                                                 0 |
+---------------------------------------------------+
NumPoints(LineString l):Integer
The number of points in this LineString.
mysql> SELECT NumPoints(GeomFromText('LineString(1 1,2 2,3 3)'));
+----------------------------------------------------+
| NumPoints(GeomFromText('LineString(1 1,2 2,3 3)')) |
+----------------------------------------------------+
|                                                  3 |
+----------------------------------------------------+
PointN(LineString l,integer n):Point
Returns the n-th point in this Linestring. Point numbers begin at 1.
mysql> SELECT AsText(PointN(GeomFromText('LineString(1 1,2 2,3 3)'),2));
+-----------------------------------------------------------+
| AsText(PointN(GeomFromText('LineString(1 1,2 2,3 3)'),2)) |
+-----------------------------------------------------------+
| POINT(2 2)                                                |
+-----------------------------------------------------------+
StartPoint(LineString l):Point
The start point of this LineString.
mysql> SELECT AsText(StartPoint(GeomFromText('LineString(1 1,2 2,3 3)')));
+-------------------------------------------------------------+
| AsText(StartPoint(GeomFromText('LineString(1 1,2 2,3 3)'))) |
+-------------------------------------------------------------+
| POINT(1 1)                                                  |
+-------------------------------------------------------------+

Note: MySQL does not yet implement the following function:

IsRing(LineString l):Integer
Returns 1 (TRUE) if this LineString is closed (the StartPoint() and EndPoint() values are the same) and is simple (does not pass through the same point more than once).

10.5.2.4 Functions To Analyse MultiLineString Properties

GLength(MultiLineString m):Double
The length of this MultiLineString, which is equal to the sum of the lengths of the elements.
mysql> SELECT GLength(GeomFromText('MultiLineString((1 1,2 2,3 3),(4 4,5 5))'));
+-------------------------------------------------------------------+
| GLength(GeomFromText('MultiLineString((1 1,2 2,3 3),(4 4,5 5))')) |
+-------------------------------------------------------------------+
|                                                   4.2426406871193 |
+-------------------------------------------------------------------+
IsClosed(MultiLineString m):Integer
Returns 1 (TRUE) if this MultiLineString is closed (the StartPoint() and EndPoint() values are the same for each LineString in this MultiLineString).
mysql> SELECT IsClosed(GeomFromText('MultiLineString((1 1,2 2,3 3),(4 4,5 5))'));
+--------------------------------------------------------------------+
| IsClosed(GeomFromText('MultiLineString((1 1,2 2,3 3),(4 4,5 5))')) |
+--------------------------------------------------------------------+
|                                                                  0 |
+--------------------------------------------------------------------+

10.5.2.5 Functions To Analyse Polygon Properties

Area(Polygon p):Double
The area of this Polygon, as measured in its spatial reference system.
mysql> SELECT Area(GeomFromText('Polygon((0 0,0 3,3 3,3 0,0 0),(1 1,1 2,2 2,2 1,1 1))'));
+----------------------------------------------------------------------------+
| Area(GeomFromText('Polygon((0 0,0 3,3 3,3 0,0 0),(1 1,1 2,2 2,2 1,1 1))')) |
+----------------------------------------------------------------------------+
|                                                                          8 |
+----------------------------------------------------------------------------+
NumInteriorRings(Polygon p):Integer
Returns the number of interior rings in this Polygon.
mysql> SELECT NumInteriorRings(GeomFromText('Polygon((0 0,0 3,3 3,3 0,0 0),(1 1,1 2,2 2,2 1,1 1))'));
+----------------------------------------------------------------------------------------+
| NumInteriorRings(GeomFromText('Polygon((0 0,0 3,3 3,3 0,0 0),(1 1,1 2,2 2,2 1,1 1))')) |
+----------------------------------------------------------------------------------------+
|                                                                                      1 |
+----------------------------------------------------------------------------------------+
ExteriorRing(Polygon p):LineString
Returns the exterior ring of this Polygon as a LineString.
mysql> SELECT AsText(ExteriorRing(GeomFromText('Polygon((0 0,0 3,3 3,3 0,0 0),(1 1,1 2,2 2,2 1,1 1))')));
+--------------------------------------------------------------------------------------------+
| AsText(ExteriorRing(GeomFromText('Polygon((0 0,0 3,3 3,3 0,0 0),(1 1,1 2,2 2,2 1,1 1))'))) |
+--------------------------------------------------------------------------------------------+
| LINESTRING(0 0,0 3,3 3,3 0,0 0)                                                            |
+--------------------------------------------------------------------------------------------+
InteriorRingN(Polygon p, Integer n):LineString
Returns the n-th interior ring for this Polygon as a LineString. Ring numbers begin at 1.
mysql> SELECT AsText(InteriorRingN(GeomFromText('Polygon((0 0,0 3,3 3,3 0,0 0),(1 1,1 2,2 2,2 1,1 1))'),1));
+-----------------------------------------------------------------------------------------------+
| AsText(InteriorRingN(GeomFromText('Polygon((0 0,0 3,3 3,3 0,0 0),(1 1,1 2,2 2,2 1,1 1))'),1)) |
+-----------------------------------------------------------------------------------------------+
| LINESTRING(1 1,1 2,2 2,2 1,1 1)                                                               |
+-----------------------------------------------------------------------------------------------+

Note: MySQL does not yet implement the following functions:

Centroid(Polygon p):Point
The mathematical centroid for this Polygon as a Point. The result is not guaranteed to be on this Polygon.
PointOnSurface(p:Polygon):Point
A point guaranteed to be on this Polygon.

10.5.2.6 Functions To Analyse MultiPolygon Properties

Area(MultiPolygon m):Double
The area of this MultiPolygon, as measured in its spatial reference system.
mysql> SELECT Area(GeomFromText('MultiPolygon(((0 0,0 3,3 3,3 0,0 0),(1 1,1 2,2 2,2 1,1 1)))'));
+-----------------------------------------------------------------------------------+
| Area(GeomFromText('MultiPolygon(((0 0,0 3,3 3,3 0,0 0),(1 1,1 2,2 2,2 1,1 1)))')) |
+-----------------------------------------------------------------------------------+
|                                                                                 8 |
+-----------------------------------------------------------------------------------+

Note: MySQL does not yet implement the following functions:

Centroid(MultiPolygon p):Point
The mathematical centroid for this MultiPolygon as a Point. The result is not guaranteed to be on this MultiPolygon.
PointOnSurface(MultiPolygon m):Point
A Point guaranteed to be on this MultiPolygon.

10.5.2.7 Functions To Analyse GeometryCollection Properties

NumGeometries(GeometryCollection g):Integer
Returns the number of geometries in this GeometryCollection.
mysql> SELECT NumGeometries(GeomFromText('GeometryCollection(Point(1 1),LineString(2 2, 3 3))'));
+------------------------------------------------------------------------------------+
| NumGeometries(GeomFromText('GeometryCollection(Point(1 1),LineString(2 2, 3 3))')) |
+------------------------------------------------------------------------------------+
|                                                                                  2 |
+------------------------------------------------------------------------------------+
GeometryN(GeometryCollection g,integer N):Geometry
Returns the n-th geometry in this GeometryCollection. Geometry numbers begin at 1.
mysql> SELECT AsText(GeometryN(GeomFromText('GeometryCollection(Point(1 1),LineString(2 2, 3 3))'),1));
+------------------------------------------------------------------------------------------+
| AsText(GeometryN(GeomFromText('GeometryCollection(Point(1 1),LineString(2 2, 3 3))'),1)) |
+------------------------------------------------------------------------------------------+
| POINT(1 1)                                                                               |
+------------------------------------------------------------------------------------------+

10.5.3 Functions That Create New Geometries From Existing Ones

10.5.3.1 Geometry Functions That Produce New Geometries

In the section section 10.5.2 Functions To Analyse Geometry Properties, we've already discussed some functions that can construct new geometries from the existing ones:

10.5.3.2 Spatial Operators

OpenGIS proposes a number of other functions that can produce geometries. They are designed to implement Spatial Operators.

Note: These functions are not yet implemented. They should appear in future releases.

Intersection(Geometry g1,g2):Geometry
A geometry that represents the point set intersection of g1 with g2.
Union(Geometry g1,g2):Geometry
A geometry that represents the point set union of g1 with g2.
Difference(Geometry g1,g2):Geometry
A geometry that represents the point set difference of g1 with g2.
SymDifference(Geometry g1,g2):Geometry
A geometry that represents the point set symmetric difference of g1 with g2.
Buffer(Geometry g, double d):Geometry
A geometry that represents all points whose distance from g is less than or equal to distance of d.
ConvexHull(Geometry g):Geometry
A geometry that represents the convex hull of g.

10.5.4 Functions For Testing Spatial Relations Between Geometric Objects

The functions described in these sections take two geometries as input parameters and return a qualitive or quantitive relation between them.

10.5.5 Relations On Geometry Minimal Bounding Rectangles (MBRs)

The current release provides some functions that can test relations between mininal bounding rectangles of two geometries. They include:

MBRContains(g1,g2)
Returns 1 or 0 to indicate whether or not the Minimum Bounding Rectangle of g1 contains the Minimum Bounding Rectangle of g2.
mysql> SELECT MBRContains(GeomFromText('Polygon((0 0,0 3,3 3,3 0,0 0))'),GeomFromText('Point(1 1)'));
+----------------------------------------------------------------------------------------+
| MBRContains(GeomFromText('Polygon((0 0,0 3,3 3,3 0,0 0))'),GeomFromText('Point(1 1)')) |
+----------------------------------------------------------------------------------------+
|                                                                                      1 |
+----------------------------------------------------------------------------------------+
MBRWithin(g1,g2)
Returns 1 or 0 to indicate whether or not the Minimum Bounding Rectangle of g1 is within the Minimum Bounding Rectangle of g2.
mysql> SELECT MBRWithin(GeomFromText('Polygon((0 0,0 3,3 3,3 0,0 0))'),GeomFromText('Polygon((0 0,0 5,5 5,5 0,0 0))'));
+----------------------------------------------------------------------------------------------------------+
| MBRWithin(GeomFromText('Polygon((0 0,0 3,3 3,3 0,0 0))'),GeomFromText('Polygon((0 0,0 5,5 5,5 0,0 0))')) |
+----------------------------------------------------------------------------------------------------------+
|                                                                                                        1 |
+----------------------------------------------------------------------------------------------------------+
MBRDisjoint(g1,g2)
Returns 1 or 0 to indicate whether or not the Minimum Bounding Rectangles of the two geometries are disjoint (do not intersect).
MBREquals(g1,g2)
Returns 1 or 0 to indicate whether or not the Minimum Bounding Rectangles of the two geometries are the same.
MBRIntersects(g1,g2)
Returns 1 or 0 to indicate whether or not the Minimum Bounding Rectangles of the two geometries intersect.
MBROverlaps(g1,g2)
Returns 1 or 0 to indicate whether or not the Minimum Bounding Rectangles of the two geometries overlap.
MBRTouches(g1,g2)
Returns 1 or 0 to indicate whether or not the Minimum Bounding Rectangles of the two geometries touch.

10.5.6 Functions That Test Spatial Relationships Between Geometries

Note: The functions in the following list are not yet implemented. When implemented, they will provide full (not MBR-based only) support for spatial analysis.

Contains(g1,g2)
Returns 1 or 0 to indicate whether or not g1 completely contains g2.
Crosses(g1,g2)
Returns 1 if g1 spatially crosses g2. Returns NULL if g1 is a polygon or a multipolygon, or if g2 is a point or a multipoint. Otherwise, returns 0. The term spatially crosses denotes a spatial relation between two given geometries that has the following properties:
Disjoint(g1,g2)
Returns 1 or 0 to indicate whether or not g1 is spatially disjoint from (does not intersect) g2.
Equals(g1,g2)
Returns 1 or 0 to indicate whether or not g1 is spatially equal to g2.
Intersects(g1,g2)
Returns 1 or 0 to indicate whether or not g1 spatially intersects g2.
Overlaps(g1,g2)
Returns 1 or 0 to indicate whether or not g1 spatially overlaps g2. The term spatially overlaps is used if two geometries intersect and their intersection results in a geometry of the same dimension but not equal to either of the given geometries.
Touches(g1,g2)
Returns 1 or 0 to indicate whether or not g1 spatially touches g2. Two geometries spatially touch if the interiors of the geometries do not intersect, but the boundary of one of the geometries intersects either the boundary or the interior of the other.
Within(g1,g2)
Returns 1 or 0 to indicate whether or not g1 is spatially within g2.
Distance(g1:Geometry,g2:Geometry):Double
The shortest distance between any two points in the two geometries.
Related(g1:Geometry,g2:Geometry,pattern_matrix:string):Double
Returns 1 or 0 to indicate whether or not the spatial relationship specified by pattern_matrix exists between g1 and g2. The pattern matrix is a string. Its specification will be noted here when this function is implemented.

10.6 Optimising Spatial Analysis

It is known that search operations in non-spatial databases can be optimised using indexes. This is true for spatial databases as well. With the help of a great variety of multi-dimensional indexing methods which have already been designed, it's possible to optimise spatial searches, the most typical of which are:

MySQL utilises R-Trees with quadratic splitting to index spatial columns. A spatial index is built using the MBR of a geometry. For most geometries, the MBR is a minimum rectangle that surrounds the geometries. For a horizontal or a vertical linestring, the MBR is a rectangle degenerated into the linestring. For a point, the MBR is a rectangle degenerated into the point.

10.6.1 Creating Spatial Indexes

MySQL can create spatial indexes in the same way it can create regular indexes. The normal syntax for creating indexes is extended with the SPATIAL keyword:

To drop spatial indexes, use ALTER TABLE or DROP INDEX:

Example: Suppose that a table g contains more than 32000 geometries, which are stored in the column g of type GEOMETRY. The table also has an AUTO_INCREMENT column fid for storing object IDs.

mysql> SHOW FIELDS FROM g;
+-------+----------+------+-----+---------+----------------+
| Field | Type     | Null | Key | Default | Extra          |
+-------+----------+------+-----+---------+----------------+
| fid   | int(11)  |      | PRI | NULL    | auto_increment |
| g     | geometry |      |     |         |                |
+-------+----------+------+-----+---------+----------------+
2 rows in set (0.00 sec)

mysql> SELECT COUNT(*) FROM g;
+----------+
| count(*) |
+----------+
|    32376 |
+----------+
1 row in set (0.00 sec)

To add a spatial index on the column g, use this statement:

mysql> ALTER TABLE g ADD SPATIAL INDEX(g);
Query OK, 32376 rows affected (4.05 sec)
Records: 32376  Duplicates: 0  Warnings: 0

10.6.2 Using a Spatial Index

The optimiser investigates whether available spatial indexes can be involved in the search for queries that use a function like MBRContains() or MBRWithin() in the WHERE clause. For example, let's say we want to find all objects that are in the given rectangle:

mysql> SELECT fid,AsText(g) FROM g WHERE
mysql> MBRContains(GeomFromText('Polygon((30000 15000,31000 15000,31000 16000,30000 16000,30000 15000))'),g);
+-----+-----------------------------------------------------------------------------+
| fid | AsText(g)                                                                   |
+-----+-----------------------------------------------------------------------------+
|  21 | LINESTRING(30350.4 15828.8,30350.6 15845,30333.8 15845,30333.8 15828.8)     |
|  22 | LINESTRING(30350.6 15871.4,30350.6 15887.8,30334 15887.8,30334 15871.4)     |
|  23 | LINESTRING(30350.6 15914.2,30350.6 15930.4,30334 15930.4,30334 15914.2)     |
|  24 | LINESTRING(30290.2 15823,30290.2 15839.4,30273.4 15839.4,30273.4 15823)     |
|  25 | LINESTRING(30291.4 15866.2,30291.6 15882.4,30274.8 15882.4,30274.8 15866.2) |
|  26 | LINESTRING(30291.6 15918.2,30291.6 15934.4,30275 15934.4,30275 15918.2)     |
| 249 | LINESTRING(30337.8 15938.6,30337.8 15946.8,30320.4 15946.8,30320.4 15938.4) |
|   1 | LINESTRING(30250.4 15129.2,30248.8 15138.4,30238.2 15136.4,30240 15127.2)   |
|   2 | LINESTRING(30220.2 15122.8,30217.2 15137.8,30207.6 15136,30210.4 15121)     |
|   3 | LINESTRING(30179 15114.4,30176.6 15129.4,30167 15128,30169 15113)           |
|   4 | LINESTRING(30155.2 15121.4,30140.4 15118.6,30142 15109,30157 15111.6)       |
|   5 | LINESTRING(30192.4 15085,30177.6 15082.2,30179.2 15072.4,30194.2 15075.2)   |
|   6 | LINESTRING(30244 15087,30229 15086.2,30229.4 15076.4,30244.6 15077)         |
|   7 | LINESTRING(30200.6 15059.4,30185.6 15058.6,30186 15048.8,30201.2 15049.4)   |
|  10 | LINESTRING(30179.6 15017.8,30181 15002.8,30190.8 15003.6,30189.6 15019)     |
|  11 | LINESTRING(30154.2 15000.4,30168.6 15004.8,30166 15014.2,30151.2 15009.8)   |
|  13 | LINESTRING(30105 15065.8,30108.4 15050.8,30118 15053,30114.6 15067.8)       |
| 154 | LINESTRING(30276.2 15143.8,30261.4 15141,30263 15131.4,30278 15134)         |
| 155 | LINESTRING(30269.8 15084,30269.4 15093.4,30258.6 15093,30259 15083.4)       |
| 157 | LINESTRING(30128.2 15011,30113.2 15010.2,30113.6 15000.4,30128.8 15001)     |
+-----+-----------------------------------------------------------------------------+
20 rows in set (0.00 sec)

Now let's check the way this query is executed, using EXPLAIN:

mysql> EXPLAIN SELECT fid,AsText(g) FROM g WHERE
mysql> MBRContains(GeomFromText('Polygon((30000 15000,31000 15000,31000 16000,30000 16000,30000 15000))'),g);
+----+-------------+-------+-------+---------------+------+---------+------+------+-------------+
| id | select_type | table | type  | possible_keys | key  | key_len | ref  | rows | Extra       |
+----+-------------+-------+-------+---------------+------+---------+------+------+-------------+
|  1 | SIMPLE      | g     | range | g             | g    |      32 | NULL |   50 | Using where |
+----+-------------+-------+-------+---------------+------+---------+------+------+-------------+
1 row in set (0.00 sec)

Now let's check what would happen if we didn't have a spatial index:

mysql> EXPLAIN SELECT fid,AsText(g) FROM g IGNORE INDEX (g) WHERE
mysql> MBRContains(GeomFromText('Polygon((30000 15000,31000 15000,31000 16000,30000 16000,30000 15000))'),g);
+----+-------------+-------+------+---------------+------+---------+------+-------+-------------+
| id | select_type | table | type | possible_keys | key  | key_len | ref  | rows  | Extra       |
+----+-------------+-------+------+---------------+------+---------+------+-------+-------------+
|  1 | SIMPLE      | g     | ALL  | NULL          | NULL |    NULL | NULL | 32376 | Using where |
+----+-------------+-------+------+---------------+------+---------+------+-------+-------------+
1 row in set (0.00 sec)

Let's execute the above query, ignoring the spatial key we have:

mysql> SELECT fid,AsText(g) FROM g IGNORE INDEX (g) WHERE
mysql> MBRContains(GeomFromText('Polygon((30000 15000,31000 15000,31000 16000,30000 16000,30000 15000))'),g);
+-----+-----------------------------------------------------------------------------+
| fid | AsText(g)                                                                   |
+-----+-----------------------------------------------------------------------------+
|   1 | LINESTRING(30250.4 15129.2,30248.8 15138.4,30238.2 15136.4,30240 15127.2)   |
|   2 | LINESTRING(30220.2 15122.8,30217.2 15137.8,30207.6 15136,30210.4 15121)     |
|   3 | LINESTRING(30179 15114.4,30176.6 15129.4,30167 15128,30169 15113)           |
|   4 | LINESTRING(30155.2 15121.4,30140.4 15118.6,30142 15109,30157 15111.6)       |
|   5 | LINESTRING(30192.4 15085,30177.6 15082.2,30179.2 15072.4,30194.2 15075.2)   |
|   6 | LINESTRING(30244 15087,30229 15086.2,30229.4 15076.4,30244.6 15077)         |
|   7 | LINESTRING(30200.6 15059.4,30185.6 15058.6,30186 15048.8,30201.2 15049.4)   |
|  10 | LINESTRING(30179.6 15017.8,30181 15002.8,30190.8 15003.6,30189.6 15019)     |
|  11 | LINESTRING(30154.2 15000.4,30168.6 15004.8,30166 15014.2,30151.2 15009.8)   |
|  13 | LINESTRING(30105 15065.8,30108.4 15050.8,30118 15053,30114.6 15067.8)       |
|  21 | LINESTRING(30350.4 15828.8,30350.6 15845,30333.8 15845,30333.8 15828.8)     |
|  22 | LINESTRING(30350.6 15871.4,30350.6 15887.8,30334 15887.8,30334 15871.4)     |
|  23 | LINESTRING(30350.6 15914.2,30350.6 15930.4,30334 15930.4,30334 15914.2)     |
|  24 | LINESTRING(30290.2 15823,30290.2 15839.4,30273.4 15839.4,30273.4 15823)     |
|  25 | LINESTRING(30291.4 15866.2,30291.6 15882.4,30274.8 15882.4,30274.8 15866.2) |
|  26 | LINESTRING(30291.6 15918.2,30291.6 15934.4,30275 15934.4,30275 15918.2)     |
| 154 | LINESTRING(30276.2 15143.8,30261.4 15141,30263 15131.4,30278 15134)         |
| 155 | LINESTRING(30269.8 15084,30269.4 15093.4,30258.6 15093,30259 15083.4)       |
| 157 | LINESTRING(30128.2 15011,30113.2 15010.2,30113.6 15000.4,30128.8 15001)     |
| 249 | LINESTRING(30337.8 15938.6,30337.8 15946.8,30320.4 15946.8,30320.4 15938.4) |
+-----+-----------------------------------------------------------------------------+
20 rows in set (0.46 sec)

When the index is not used, the execution time for this query rises from 0.00 seconds to 0.46 seconds.

In future releases, spatial indexes will also be used for optimising other functions. See section 10.5.4 Functions For Testing Spatial Relations Between Geometric Objects.

10.7 MySQL Conformance And Compatibility

10.7.1 GIS Features That Are Not Yet Implemented

Additional Metadata Views
OpenGIS specifications propose several additional metadata views. For example, a system view named GEOMETRY_COLUMNS contains a description of geometry columns, one row for each geometry column in the database.
Functions to add/drop spatial columns
OpenGIS assumes that columns can be added or dropped using special AddGeometryColumn() and DropGeometryColumn() functions. In MySQL, this is done using the ALTER TABLE, CREATE INDEX, and DROP INDEX statements instead.
Factors related to Spatial Reference Systems and their IDs (SRIDs):
The OpenGIS function Length() on LineString and MultiLineString currently should be called in MySQL as GLength()
The problem is that it conflicts with the existing SQL function Length() that calculates the length of string values, and sometimes it's not possible to distinguish whether the function is called in a textual or spatial context. We need either to solve this somehow, or decide on another function name.


Go to the first, previous, next, last section, table of contents.