Bewise

Nous développons... votre avance

SQL Server 2008 - Fonctionnalités spatiales

DGD
22/05/2008 - Jean-Pierre Riehl
Télécharger la version Word
Télécharger les sources

Introduction

Cet article se veut une première introduction aux nouveaux types spatiaux de SQL Server 2008. Je vais vous les présenter et nous les manipulerons. Nous aborderons aussi leur utilisation avec du code .NET. Enfin, nous utiliserons Virtual Earth pour présenter les données géographiques mais nous ne rentrerons pas dans le détail de cette technologie.

L’aventure « Spatial »

SQL Server 2008 apporte dans son lot de nouveautés le support des données spatiales. Mais que cache-t-on derrière ce terme spatial. En fait, ce type de donnée va servir à représenter des informations géographiques. Dans cette catégorie, on inclut les données vectorielles comme des points (coordonnées GPS, points dans un plan, etc. [1]) mais aussi des lignes et des polygones.

Toutes ces données vectorielles respectent des standards, ceux définis par l’OGC (Open Geospatial Consortium) dont Microsoft est membre actif comme tous les autres grands du secteur. Le respect de ces standards est indispensable pour la compatibilité et l’interopérabilité avec les systèmes existants et Microsoft ne s’y trompe pas.

Alors à quoi ressemble une donnée spatiale ? On peut la représenter selon 3 formats :

  • WKT : Well-Known Binary
  • WKB : Well-Known Text
  • GML : Geography Markup Language

Que l’on représente la donnée en binaire, en XML ou en texte, on retrouve toujours ce genre de langage de description :

  • POINT (43.6042618680962 1.44367218017578) 
  • POLYGON((1 0, 0 1, 1 2, 2 1, 1 0), (2 0, 1 1, 2 2, 3 1, 2 0))

Vous trouverez plus loin des exemples avec toutes les possibilités de données.

Cependant, il faut noter que ces données doivent se classer dans 2 domaines bien distincts : la géométrie et la géodésique. Le premier s’utilise dans un plan avec des coordonnées X/Y alors que le second se base sur la forme de la terre (qui n’est pas tout à fait ronde), avec des coordonnées latitude/longitude.

Les nouveaux types

Du fait de ces 2 domaines de représentation, on distingue 2 types dans SQL Server 2008 :

  • geometry : pour le système géométrique
  • geography : pour le système géodésique

Néanmoins, ces 2 types se basent sur la même hiérarchie de classes.

hiérarchie des types spatiaux

Figure 1 - Les types spatiaux (source BOL)

A noter que tous ces types sont des types CLR.

Pour instancier le bon objet, il suffit d’appeler une des méthodes statiques d’un des 2 types et de lui passer les informations de construction au format binaire ou texte.

Objet géographique

Méthode

WKT

Point

STPointFromText

POINT(x y)

Ligne

STLineFromText

LINESTRING(x1 y1,…,xn yn)

Polygone

STPolyFromText

POLYGON(x1 y1,…,xn yn, x1 y1)

Collections

STMxxxFromText

MULTILINESTRING((x1 y1,…,xn yn), …)

MULTIPOINT((x y), (z w), …)

MULTIPOLYGON(…)

Notez que toutes les méthodes ont un équivalent binaire de la forme STxxxFromWKB. Egalement, toutes ces créations d’objets peuvent être faites par une méthode générique : STGeomFromText.

Voici quelques exemples d’instanciation d’objets spatiaux :

DECLARE @geom geometry = geometry::STMPolyFromText('MULTIPOLYGON (((5 5, 10 5, 10 10, 5 5)), ((10 10, 100 10, 200 200, 30 30, 10 10)))', 0);
DECLARE @geom2 geometry = geometry::STPointFromText('POINT (0 0)', 0);

DECLARE @geog geography = geography::STGeomFromText('LINESTRING(43.14 3.108, 43.145 3.13)', 4326);
DECLARE @geog2 geography = geography::Parse('POINT(43.13043037365261 3.1371116638183527)');

 

Que ce soit un type geometry ou geography, vous noterez un second paramètre passé en plus du WKT. Ce paramètre est le SRID pour Spatial Reference ID. Il indique quel système de calcul est retenu. Pour un type geometry, il sera égal à 0 car nous somme dans un plan simple. Pour le type geography, on prendra la valeur 4326 qui correspond au système standard. A noter que la méthode Parse prend la valeur par défaut (0 pour geometry, 4326 pour geography).

On peut connaitre la liste des SRID disponibles grâce à la vue système suivante :

select * from sys.spatial_reference_systems

A l’inverse, pour obtenir une lecture plus lisible des valeurs on utilisera la méthode STAsText qui nous retourne le WKT. On notera aussi les méthodes STX et STY qui permettent de récupérer les coordonnées d’un point géométrique.

Select @geog.STAsText()
Select @geom2.STX

Après ce petit aperçu de ces nouveaux types, voyons leur utilisation dans une table. Il n’y a pas de manipulation particulière, les 2 nouveaux types s’utilisent comme tous les autres :

CREATE TABLE CustomerPlaces
( CustomerId int,
    Localization geography, 
    LocalizationString AS Localization.STAsText()
);

CREATE TABLE Shapes
(
ShapeName varchar(50),
Layer int,
Color char(6),
Shape geometry
);

 

Pour l’insertion, on choisira indépendamment un simple parsing ou une instanciation bien qualifiée.

Premières requêtes

Les 2 nouveaux types proposent toute une série de méthodes pour manipuler des données spatiales. Aire de la surface, surface circonscrite, inscrite, périmètre, intersection, union, barycentre… Le but n’est pas de vous les décrire ici une à une. Nous allons toutefois en utiliser quelques unes dans des requêtes simples mais indispensables dans une application gérant des types spatiaux.

Tout d’abord, voyons comment retrouver les points contenus dans une zone donnée. Comme cas concret, on peut imaginer une recherche d’appartements ou d’hôtels dans une zone définie. Pour cela, nous avons plusieurs possibilités avec les méthodes STContains, STIntersects et STWithin. La méthode STIntersects serra utilisée pour le type geography car les 2 autres n’existent que sur le type geometry. Voici le code T-SQL permettant cette requête :

Declare @zone geography = geography::STPolyFromText('POLYGON((43 3.2, 43 3.5, 43.2 3.5, 43.2 3.2, 43 3.2))', 4326)

Select *
From CustomerPlaces
Where @zone.STIntersects(CustomerPlaces.Localization) = 1


Declare
@outShape geometry = geometry::STPolyFromText('POLYGON((0 0, 0 1, 1 1, 1 0, 0 0))', 4326)


Select
*
From Shapes
Where @outShape.STContains(Shapes.Shape) = 1

Select *
From Shapes
Where Shape.STWithin(@outShape) = 1

 

La différence entre ces méthodes est l’inclusion complète ou partielle de l’élément dans la zone recherchée mais pour des points, cela ne posera pas de problèmes.

En second exemple, on veut retrouver le ou les points les plus proches d’un point donné. Le cas concret associé est de trouver un parking ou la station météo la plus proche. Pour atteindre ce résultat, nous allons utiliser la méthode STDistance.

DECLARE @currentPlace geography = geography::Parse('POINT(43.13043037365261 3.1371116638183527)');

Select  top 1 CustomerID
From CustomerPlaces
Where Localization.STDistance(@currentPlace) < 300

 

Indexation

Les méthodes présentées ci-dessus permettent de retrouver facilement des points. Cependant, dans une table contenant des centaines de milliers de points, on pourrait s’inquiéter des performances. En effet, pour obtenir le résultat, le moteur de requête est obligé de lire toute la table, de charger tous les types dans la CLR et d’effectuer le calcul, comme on peut le voir sur le plan d’exécution suivant.

plan d'éxecution sans index

Figure 2 - Plan d'exécution d'une recherche sans index spatial

Pour améliorer les performances, ce type ne pouvait pas s’accompagner d’un système d’indexation. SQL Server s’enrichit donc d’un nouveau type d’index : les index spatiaux.

Pourquoi ne pas avoir utilisé les index classiques de SQL Server ? Tout simplement parce qu’on doit placer des points dans l’espace et que la manière dont est représentée une clé dans un B-Tree classique ne le permet pas.

La méthode d’indexation utilisée est la « tesselation » (ou maillage). La surface est découpée en zones égales, chaque zone est elle-même découpée et ainsi de suite sur plusieurs niveaux. Le principe du B-Tree est conservé puisqu’il permet de naviguer dans les différentes zones pour atteindre celle du point ou de la forme que l’on recherche. Le schéma suivant illustre ce principe.

index spatiaux

Figure 3 - Index spatiaux (source BOL)

La création de l’index ressemble à la création d’un index classique. On ajoute juste le mot-clé SPATIAL et quelques options de tuning.

CREATE SPATIAL INDEX [IX_Places] ON [dbo].[CustomerPlaces]
(
      [Localization]
) USING  GEOGRAPHY_GRID
WITH (CELLS_PER_OBJECT = 16);

 

Toutes les méthodes des types spatiaux ne s’appuient pas sur les index spatiaux. Les méthodes suivantes en tirent partie, elles correspondent à la recherche de points (ou éléments) et aux questions de recoupage (contenance, intersection).

  • geometry1.STContains( geometry2 ) = 1
  • geometry1.STDistance ( geometry2 ) < number
  • geometry1.STDistance ( geometry2 ) <= number
  • geometry1.STEquals ( geometry2 ) = 1
  • geometry1.STIntersects ( geometry2 ) = 1
  • geometry1.STOverlaps (geometry2) = 1
  • geometry1.STTouches ( geometry2 ) = 1
  • geometry1.STWithin ( geometry2 ) = 1

Attention, contrairement à un index classique qui pourrait être utilisé sur un opérateur de type ORDER BY, l’index spatial ne s’utilisera que dans une clause WHERE.

Le résultat de l’utilisation d’un index spatial dans le plan d’exécution est le suivant :

plan d'exécution avec index

Figure 4 - Plan d'exécution d'une recherche avec un index spatial

Ici je ne montre qu’une partie du plan d’exécution car il est bien plus complexe qu’un simple opérateur Index Seek. L’utilisation de la tesselation implique plusieurs opérations internes avant d’interroger l’index spatial.

Le résultat de l’indexation est encore plus flagrant avec le SQL Profiler :

resultat de l'indexation

Figure 5 - Impact sur les performances d'un index spatial

On gagne plus de 70% sur les lectures logiques. Mais le plus remarquable est le gain en temps CPU car c’est le calcul qui est optimisé. La conséquence, c’est que l’on passe d’une requête de près de 11s à une requête de 36ms.

ADO.NET

Après avoir vu un aperçu des types spatiaux et de leur utilisation dans SQL dans Management Studio, intéressons nous à la manipulation depuis une application .NET.

A ce jour, il n’existe pas d’update d’ADO.NET qui supporte nativement les types spatiaux. Vous avez néanmoins à disposition l’Assembly Microsoft.SqlSever.Types qui contient les types CLR de SQL Server 2008. Vous la trouverez dans le GAC en version 10.0.

 image

Figure 6 - Assembly des nouveaux types SQL Server 2008

On trouve dans cette Assembly un type SqlGeography et un type SqlGeometry que vous pouvez utiliser dans vos applications en bénéficiant de l’instanciation d’éléments spatiaux et de leur manipulation via les méthodes décrites plus haut (STDistance, STIntersects, etc.). Ce sont les mêmes types que ceux de la SQLCLR.

Cependant, ces types ne peuvent pas être utilisés dans des paramètres d’une SqlCommand. Nous allons contourner cette limitation en utilisant des types existants : varchar et varbinary.

Nous avons vu que l’on pouvait représenter un type spatial via les formats WKT et WKB (Well-Known Text et Well-Known Binary). Pour ce qui est du texte, on pourrait construire le WKT par une manipulation de chaine, mais il est plus simple d’utiliser le type SqlGeography mis à notre disposition. Ce dernier dispose des méthodes STAsText et STAsBinary. Reste à passer ça à une SqlCommand classique.

/*
 * On crée la structure spatiale
 */
SqlGeography g = SqlGeography.Point(Latitude, Longitude, 4326);

using
(SqlConnection cnn = new SqlConnection(connectionStr))
{
    using (SqlCommand cmd = cnn.CreateCommand())
    {
        cmd.CommandType = CommandType.StoredProcedure;
     
        cmd.CommandText = @"CustomerPlaces_I_WKT";
        cmd.Parameters.Add("@WKT", SqlDbType.VarChar).Value = g.STAsText();
//
on transforme en WKT (well-known type)

       
cnn.Open();
        cmd.ExecuteNonQuery();
    }
}

 

La variante utilisant le binaire est la suivante :

cmd.CommandText = @"CustomerPlaces_I_WKB";
cmd.Parameters.Add("@WKB", SqlDbType.VarBinary).Value = g.STAsBinary();
//on transforme en WKB (well-known binary)

 

 

Alors, quelle méthode préférer pour la manipulation des types spatiaux dans une application .NET ? Des tests de performances vont permettre de statuer sur le choix.

Premièrement, la méthode STAsBinary est 30% moins performante que STAsText dans le code .NET lors de mes essais (100.000 appels). Mais qu’en est-il de l’interprétation côté serveur ?

Coté serveur, j’ai créé 3 procédures stockées. Une pour le texte et une pour le binaire utilisant respectivement les méthodes STGeomFromWKB et STGeomFromText. Et une troisième n’utilisant aucune méthode mais faisant une insertion avec un CAST implicite.

Create Procedure CustomerPlaces_I_WKB
(
      @WKB as varbinary(1024)
)
As
Begin
      Declare @g geography = geography::STGeomFromWKB(@WKB, 4326)
     
      Insert into Demo.dbo.CustomerPlaces(Localization) Values (@g)
End
go


Create
Procedure CustomerPlaces_I_WKT
(
      @WKT as varchar(1024)
)
As
Begin
      Declare @g geography = geography::STGeomFromText(@WKT, 4326)
     
      Insert into Demo.dbo.CustomerPlaces(Localization) Values (@g)
End
go

Create Procedure CustomerPlaces_I_Native
(
      @WKT as varchar(1024)
)
As
Begin 
      Insert into Demo.dbo.CustomerPlaces(Localization) Values (@WKT)
End
go

 

La trace faite sur les différents appels montre que l’utilisation du binaire comme format pivot (3ème appel) est à exclure. On voit aussi qu’un transtypage implicite (2ème appel) permet de gagner encore un peu

performance ADO.NET

Figure 7 - Performances ADO.NET

Affichage avec Virtual Earth

Reste un point à traiter, l’affichage des données spatiales. Bien sûr, en fonction de l’utilisation que vous souhaitez faire de ces nouveaux types, vos besoins en restitution peuvent être très différents. Toutefois, il est un mode de restitution incontournable, c’est l’affichage des points ou des zones sur une carte.

Virtual Earth nous permet de faire cette restitution. Cette technologie permet d’avoir accès aux cartes de l’ensemble du globe et de dessiner des points ou des formes dessus, correspondant à nos données spatiales. Cet article ne présente pas en profondeur cette technologie, je vous renvoie à la série d’articles de Bewise à venir sur le sujet écrite par Philippe Lonvaud qui détailleront Virtual Earth.

Ce qu’il faut retenir, c’est que Virtual Earth travaille avec des coordonnées de type longitude/latitude. On manipule les cartes avec du JavaScript. Pour plus de facilité, on peut l’encapsuler dans un extender Ajax pour manipuler le tout via contrôle ASP.NET.

[TargetControlType(typeof(Panel))]
public class VirtualEarthExtender : ExtenderControl
{
    /// <summary>
    /// Gets or sets the initial latitude.
    /// </summary>
    public double InitialLatitude {}


   
/// <summary>
    /// Gets or sets the initial longitude.
    /// </summary>
    public double InitialLongitude {}


   
/// <summary>
    /// Gets or sets the zoom level.
    /// </summary>
    public int ZoomLevel {}
}

 

Pour ajouter les points, on doit récupérer les valeurs. Pour cela, nous allons faire appel aux méthodes des types SqlGeography et SqlGeometry coté serveur ET côté client. Côté serveur, on exporte les données spatiales sous la forme WKT et on reconstruit un objet SqlGeography coté client.

string command = @"
  select top 1 EmployeeID, Localization.STAsText() as LocalizationText, Comment, [When]
  from dbo.Localizations
  where EmployeeID = @empID
  order by [When] desc";
...
SqlGeography gText = SqlGeography.STGeomFromText(dr.GetSqlChars(dr.GetOrdinal("LocalizationText")), 4326);

l.Latitude = gText.Lat.Value;
l.Longitude = gText.Long.Value;

 

Il n’y a plus qu’à passer ces coordonnées à Virtual Earth pour l’affichage via le code JavaScript :

var pushpinLocation = new VELatLong(pushpinData.Latitude, pushpinData.Longitude);
var shape = new VEShape(VEShapeType.Pushpin, pushpinLocation);
// Add pushpin to the map.
this._instance.AddShape(shape);      

 

représentation dans VE

Figure 8 - Représentation de points dans Virtual Earth

Conclusion

Voila pour une première approche des types spatiaux dans SQL Server 2008. Certes le sujet mérite de nombreux articles qui viendront par la suite.

Notamment, pour aller plus loin, je creuserai dans les articles à venir l’utilisation des types spatiaux dans différents scénarios et avec les différents outils de l’écosystème Microsoft. Entre autre, j’aborderai l’utilisation du type spatial dans un projet décisionnel et sa manipulation dans Integration Services.

N’oubliez pas de consulter la série d’article sur Virtual Earth, écrite par Philippe Lonvaud, qui sera bientôt mise à disposition pour présenter et creuser cette technologie. Restez à l’écoute. 

 


[1] Tous ces types d’informations géographiques seront détaillés dans un article consacré à Virtual Earth.

> Tous les articles

Commentaires

aucun commentaire
Page 1/1
     
Connexion
  • Accueil
  • Plan du site
  • Contact
Les blogs de l'équipe

Votre carrière et nous

  • Nos offres
  • Votre candidature

Technologies

  • Actualités
  • Articles
  • Webcasts
  • Toolbox
Ignorer les liens de navigation > Accueil > Technologies > Détail Article
Ignorer les liens de navigation
Nous
Nos Métiers
Vous Former
Technologies
Nos Références
Nos Activités
Nos Certifications
Nos Chiffres
Votre Carrière et Nous
Le Groupe
Nos Partenaires
On Parle de Nous
Nous contacter
Administrateur Système & Réseaux
Défiler vers le haut
Défiler vers le bas
Administration, Système et Communication
Architecture, Méthodes, Industrialisation
Décisionnel et Gestion des Données
Nouvelles Interfaces Utilisateurs
Portail et Travail Collaboratif
Solutions Langages et Framework
Solutions Web Avancées
Défiler vers le haut
Défiler vers le bas
Nos cours
Le Planning
Offres promotionnelles
Défiler vers le haut
Défiler vers le bas
Actualités
Articles
Webcasts
Blogs
Toolbox
Evénements
Défiler vers le haut
Défiler vers le bas
  • Infos légales
  • Lettre du Regional Director
  • Revue de presse