{"id":107053,"date":"2025-07-08T14:44:28","date_gmt":"2025-07-08T14:44:28","guid":{"rendered":"https:\/\/www.red-gate.com\/simple-talk\/?p=107053"},"modified":"2025-06-16T10:14:26","modified_gmt":"2025-06-16T10:14:26","slug":"creating-uber-fast-maps-with-23ai-vector-tiles-and-h3-indexes-part-1","status":"publish","type":"post","link":"https:\/\/www.red-gate.com\/simple-talk\/databases\/oracle-databases\/creating-uber-fast-maps-with-23ai-vector-tiles-and-h3-indexes-part-1\/","title":{"rendered":"Creating Uber-Fast Maps With 23ai Vector Tiles and H3 Indexes: Part 1"},"content":{"rendered":"\n<p><em><a href=\"https:\/\/www.oracle.com\/database\/23ai\/\">Oracle Database 23ai<\/a> added 300+ new features like the new VECTOR datatype that get most of the attention, but often overlooked are two new features that dramatically expand support for complex geospatial problem-solving. In this article we\u2019ll take a closer look at <\/em><strong><em>vector tiling<\/em><\/strong><em> \u2013 a toolset that already has everything your developers need to create ultra-fast maps in standard geospatial applications. <\/em><\/p>\n\n\n\n<p>OK, I have to admit it: I\u2019m a map junkie. I\u2019ve built all kinds of mapping applications for the past several years using either Oracle APEX\u2019s Native Map Region (NMR) toolset when I wanted a low-code solution with excellent control over features like legends and layers, and Oracle Spatial Studio when I didn\u2019t have time to write complex SQL to quickly review how spatial data was distributed.<\/p>\n\n\n\n<p>One pain point I\u2019ve run into involves response time, especially when I\u2019m displaying tens or even hundreds of thousands of individual points on a map on different layers. Even my laptop with a reasonably robust GPU and memory cannot cope with those demands. For example, the map in <strong>Figure 1<\/strong> was built in APEX 24.2 using NMR to display over <strong>157,000<\/strong> separate longitude\/latitude points on three different map layers, and it typically takes between 45 &#8211; 180 seconds to load completely. My pain is not new or just my pain; loading map content quickly when there are huge volumes of individual points to display has been a challenge for GIS applications since they were first born in the mid-1960s.<\/p>\n\n\n\n<figure class=\"wp-block-image\"><img loading=\"lazy\" decoding=\"async\" width=\"1173\" height=\"736\" src=\"https:\/\/www.red-gate.com\/simple-talk\/wp-content\/uploads\/2025\/06\/a-screenshot-of-a-computer-screen-ai-generated-co.png\" alt=\"A screenshot of a computer screen\n\nAI-generated content may be incorrect.\" class=\"wp-image-107054\" srcset=\"https:\/\/www.red-gate.com\/simple-talk\/wp-content\/uploads\/2025\/06\/a-screenshot-of-a-computer-screen-ai-generated-co.png 1173w, https:\/\/www.red-gate.com\/simple-talk\/wp-content\/uploads\/2025\/06\/a-screenshot-of-a-computer-screen-ai-generated-co-300x188.png 300w, https:\/\/www.red-gate.com\/simple-talk\/wp-content\/uploads\/2025\/06\/a-screenshot-of-a-computer-screen-ai-generated-co-1024x643.png 1024w, https:\/\/www.red-gate.com\/simple-talk\/wp-content\/uploads\/2025\/06\/a-screenshot-of-a-computer-screen-ai-generated-co-768x482.png 768w\" sizes=\"auto, (max-width: 1173px) 100vw, 1173px\" \/><\/figure>\n\n\n\n<p><\/p>\n\n\n\n<p><strong><em>Figure 1. Displaying +157K Distinct Geographic Points in Oracle APEX 24.2<\/em><\/strong><\/p>\n\n\n\n<p>But there\u2019s good news for Oracle developers working with geospatial applications today: There\u2019s an intriguing solution in Oracle Database 23ai that significantly reduces map response time. <em>Vector tiles<\/em> encode all mapping data &#8211; both point \/ polygonal information and corresponding metadata &#8211; into a unique compressed binary format so specialized GIS applications like <a href=\"https:\/\/qgis.org\/\">QGIS<\/a> or <a href=\"https:\/\/www.envitia.com\/for-developers\/maplink-pro\/\">MapLink<\/a> can interpret and display this format at blinding speed.<\/p>\n\n\n\n<p>Since the size of the data for vector tiles is dramatically smaller than previous formats, network response time is also reduced, so ultimately response time for any map activity \u2013 scrolling, zooming, or selecting individual points and displaying their metadata \u2013 often improves by several orders of magnitude.<\/p>\n\n\n\n<h2 class=\"wp-block-heading\" id=\"h-so-what-are-vector-tiles\">So, What Are Vector Tiles?<\/h2>\n\n\n\n<p>The easiest way to envision vector tiles is to imagine a Mercator map projection of the surface of the Earth. The resulting projection of that geometry onto a flat surface results in a series of evenly-sized squares that can be grouped into just four at the lowest zoom level (<strong>Figure 2<\/strong>).<\/p>\n\n\n\n<figure class=\"wp-block-image size-large\"><img loading=\"lazy\" decoding=\"async\" width=\"1024\" height=\"541\" src=\"https:\/\/www.red-gate.com\/simple-talk\/wp-content\/uploads\/2025\/07\/Fig_02-1024x541.png\" alt=\"\" class=\"wp-image-107082\" srcset=\"https:\/\/www.red-gate.com\/simple-talk\/wp-content\/uploads\/2025\/07\/Fig_02-1024x541.png 1024w, https:\/\/www.red-gate.com\/simple-talk\/wp-content\/uploads\/2025\/07\/Fig_02-300x158.png 300w, https:\/\/www.red-gate.com\/simple-talk\/wp-content\/uploads\/2025\/07\/Fig_02-768x405.png 768w, https:\/\/www.red-gate.com\/simple-talk\/wp-content\/uploads\/2025\/07\/Fig_02.png 1218w\" sizes=\"auto, (max-width: 1024px) 100vw, 1024px\" \/><\/figure>\n\n\n\n<p><strong><em>Figure 2. Vector Tiles: Grouping Ever-Lower Levels of Mercator Projection Squares<\/em><\/strong><\/p>\n\n\n\n<p>Here\u2019s the real brilliance of vector tiles: At the <em>next<\/em> lowest zoom level, each one of those four squares also contains <em>another<\/em> set of four squares, which at the next zoom level contains yet <em>another<\/em> four squares, and so on until we reach a zoom level of 22, or 2<sup>23<\/sup> squares. At this lowest level, each vector tile is a square that\u2019s just under one square meter in area.<\/p>\n\n\n\n<p>Vector tiles work really well for mapping applications because at a high zoom level, it\u2019s easy to see where points are <em>concentrated<\/em> on a map, and as you drill down into the lowest levels of the map, the points are already present so there\u2019s no need to make another round trip to the map server to retrieve them and any related metadata.<\/p>\n\n\n\n<h2 class=\"wp-block-heading\" id=\"h-vector-tiles-preparing-for-implementation\">Vector Tiles: Preparing For Implementation<\/h2>\n\n\n\n<p>Let\u2019s illustrate how easy it is to leverage 23ai\u2019s vector tile capabilities with a straightforward use case: A public utility is researching where it should place long-term battery storage sites close enough to existing wind turbines, solar panel farms, and other renewable energy resources it\u2019s planning to develop. Since EVs aren\u2019t going to disappear and are likely to increase among its customer base, the utility also needs to identify all existing EV charging stations so they can provide them with energy captured at the battery storage sites.<\/p>\n\n\n\n<p>To build out this use case, I\u2019ve created and populated three different tables containing geolocations for <em>EV charging stations, wind turbines, <\/em>and<em> photovoltaic (PV) solar panel farms<\/em> throughout the United States. These data were downloaded and curated from the US National Renewal Energy Laboratory (NREL) <a href=\"https:\/\/GetProperNRELLinks.html\">website<\/a>, and contains site-specific information including each wind turbine\u2019s latitude and longitude.<\/p>\n\n\n\n<p class=\"has-base-font-size\" style=\"padding-right:var(--wp--preset--spacing--sm);padding-left:var(--wp--preset--spacing--sm)\"><strong>Note<\/strong>: in the <a href=\"#appendix\">Appendix<\/a> at the end of this article, you can find details about how to get the structures and data to test this out yourself.<\/p>\n\n\n\n<p>To keep this example simpler for now, I\u2019ll focus on the <code>EXISTING_WIND_TURBINES<\/code> table. The DDL to create that table is shown in <strong>Figure<\/strong> <strong>3<\/strong>.<\/p>\n\n\n\n<div class=\"wp-block-urvanov-syntax-highlighter-code-block\"><pre class=\"block lang:plsql\" highlight=\"true\" decode=\"true\">DROP TABLE IF EXISTS existing_wind_turbines PURGE;\nCREATE TABLE IF NOT EXISTS existing_wind_turbines (\n  usgs_case_id NUMBER(10)\n, faa_digital_obstacle_id VARCHAR2(10)\n, faa_aeronautical_study_nbr VARCHAR2(20)\n, usgs_prior_id NUMBER(10)\n, eia_860_id NUMBER(10)\n, state_abbr VARCHAR2(02)\n, county VARCHAR2(60)\n, fips VARCHAR2(09)\n, project_name VARCHAR2(60)\n, project_year NUMBER(04)\n, project_turbines NUMBER(05)\n, project_capacity NUMBER(15,03)\n, manufacturer VARCHAR2(80)\n, model VARCHAR2(40)\n, turbine_capacity NUMBER(15,03)\n, turbine_hub_height NUMBER(15,03)\n, turbine_rotor_diameter NUMBER(15,03)\n, turbine_rotor_swept_area NUMBER(15,03)\n, turbine_total_height NUMBER(15,03)\n, is_turbine_retrofitted NUMBER(01)\n, retrofit_yr NUMBER(04)\n, is_turbine_offshore NUMBER(01)\n, turbine_attribute_confidence NUMBER(01)\n, turbine_location_confidence NUMBER(01)\n, imaged_on DATE\n, image_source VARCHAR2(20)\n, longitude NUMBER(15,08)\n, latitude NUMBER(15,08)\n, geometry SDO_GEOMETRY\n);\n\nALTER TABLE existing_wind_turbines\n  ADD CONSTRAINT existing_wind_turbines_pk\n  PRIMARY KEY (usgs_case_id)\n  USING INDEX (\n    CREATE UNIQUE INDEX existing_wind_turbines_pk_idx\n        ON existing_wind_turbines (usgs_case_id)\n    );<\/pre><\/div>\n\n\n\n<p><strong><em>Figure 3. <code>EXISTING_WIND_TURBINES<\/code> Table Creation<\/em><\/strong><\/p>\n\n\n\n<p>After uploading the data via the SQL Web Developer data loading facility, I updated the contents of the <code>GEOMETRY <\/code>column with the longitude and latitude of every wind turbine site. Finally, I created a <em>spatial index<\/em> on each table\u2019s <code>GEOMETRY <\/code>column (<strong>Figure 4<\/strong>), thus enabling the geospatial features of the <code>SDO_GEOMETRY<\/code> datatype so that mapping technology could interact with that column\u2019s data.<\/p>\n\n\n\n<div class=\"wp-block-urvanov-syntax-highlighter-code-block\"><pre class=\"block lang:plsql\" highlight=\"true\" decode=\"true\">UPDATE existing_wind_turbines \n   SET geometry = SDO_GEOMETRY(longitude, latitude);\n\nCOMMIT;\n\nDROP INDEX IF EXISTS existing_wind_turbines_spidx;\nCREATE INDEX IF NOT EXISTS existing_wind_turbines_spidx\n  ON existing_wind_turbines (geometry)\n  INDEXTYPE IS MDSYS.SPATIAL_INDEX_V2\n  PARAMETERS ('LAYER_GTYPE=POINT');<\/pre><\/div>\n\n\n\n<p><strong><em>Figure 4. Updating <code>EXISTING_WIND_TURBINES.GEOMETRY<\/code> and Creating Its Spatial Index<\/em><\/strong><\/p>\n\n\n\n<h2 class=\"wp-block-heading\" id=\"h-building-vector-tile-output-from-an-sdo-geometry-column\">Building Vector Tile Output From an SDO_GEOMETRY Column<\/h2>\n\n\n\n<p>Returning geospatial data from the <code>EXISTING_WIND_TURBINES<\/code> table as a series of vector tiles in binary format is remarkably simple to accomplish via the new 23ai <code>SDO_UTIL.GET_VECTORTILE<\/code> function. Note that in this case, I specified the exact zoom level and X and Y coordinates of the tiles I\u2019m interested in retrieving (<strong>Figure 5<\/strong>), but we\u2019ll look at parameterizing this function call shortly.<\/p>\n\n\n\n<div class=\"wp-block-urvanov-syntax-highlighter-code-block\"><pre class=\"block lang:plsql\" highlight=\"true\" decode=\"true\">SELECT SDO_UTIL.GET_VECTORTILE(\n   TABLE_NAME=&gt;'EXISTING_WIND_TURBINES',\n   GEOM_COL_NAME=&gt;'GEOMETRY',\n   ATT_COL_NAMES=&gt;\n     SDO_STRING_ARRAY('USGS_CASE_ID','COUNTY','STATE_ABBR'\n                     ,'TURBINE_TOTAL_HEIGHT','TURBINE_CAPACITY'\n                     ,'LONGITUDE','LATITUDE'),\n   TILE_X=&gt;129, TILE_Y=&gt;187, TILE_ZOOM=&gt;9, MAX_FEATURES=&gt;255)\n   AS gobbledygook;<\/pre><\/div>\n\n\n\n<p><strong><em>Figure 5. Generating Limited Vector Tile Output from <code>EXISTING_WIND_TURBINES<\/code><\/em><\/strong><\/p>\n\n\n\n<p>So what gets returned from the query in <strong>Figure 5<\/strong>? Here\u2019s a snippet of the resulting output (<strong>Figure 6<\/strong>); you\u2019ll note it appears as gibberish on first glance. However, a spatial application that consumes this output sees this binary output as <em>tightly-compressed spatial data<\/em> comprising the vector tiles themselves as well as any specific metadata about each point. The spatial application can then display the vector tiles within a separate mapping layer at extreme speed without the need to make a return trip to the sending server.<\/p>\n\n\n\n<figure class=\"wp-block-image\"><img loading=\"lazy\" decoding=\"async\" width=\"944\" height=\"742\" src=\"https:\/\/www.red-gate.com\/simple-talk\/wp-content\/uploads\/2025\/06\/word-image-107053-3.png\" alt=\"\" class=\"wp-image-107056\" srcset=\"https:\/\/www.red-gate.com\/simple-talk\/wp-content\/uploads\/2025\/06\/word-image-107053-3.png 944w, https:\/\/www.red-gate.com\/simple-talk\/wp-content\/uploads\/2025\/06\/word-image-107053-3-300x236.png 300w, https:\/\/www.red-gate.com\/simple-talk\/wp-content\/uploads\/2025\/06\/word-image-107053-3-768x604.png 768w\" sizes=\"auto, (max-width: 944px) 100vw, 944px\" \/><\/figure>\n\n\n\n<p><br>  <\/p>\n\n\n\n<p><strong><em>Figure 6. <code>GET_VECTORTILE <\/code>Function: Sample Output<\/em><\/strong><\/p>\n\n\n\n<h2 class=\"wp-block-heading\" id=\"h-generating-vector-tiles-via-ords-rest-api\">Generating Vector Tiles Via ORDS REST API<\/h2>\n\n\n\n<p>The trick to transforming these vector tiles into something that mapping software can use to display them is leveraging Oracle\u2019s <code>ORDS REST<\/code> API toolset. <strong>Figure 7<\/strong> shows how I built an <code>ORDS REST API<\/code> <em>module<\/em> named <code>wind_turbines<\/code>, defined a corresponding <em>template<\/em> that accepts variable values, and finally defined a <em>handler<\/em> that returns just the required appropriate vector tiles as a <code>BLOB<\/code> based on the parameter values specified.<\/p>\n\n\n\n<div class=\"wp-block-urvanov-syntax-highlighter-code-block\"><pre class=\"lang:plsql highlight:0 decode:true block\">BEGIN\n   ORDS.DELETE_MODULE(wind_turbines');\nEND;\n\/\n\nBEGIN\n  ORDS.DEFINE_MODULE(\n    P_MODULE_NAME =&gt; 'wind_turbines'\n  , P_BASE_PATH =&gt; '\/existing_turbines\/'\n  , P_ITEMS_PER_PAGE =&gt; 50\n  , P_STATUS =&gt; 'PUBLISHED'\n  );\n  COMMIT;\nEND;\n\/\n\nBEGIN\n  ORDS.DEFINE_TEMPLATE(\n    P_MODULE_NAME =&gt; 'wind_turbines'\n  , P_PATTERN =&gt; 'vt\/:z\/:x\/:y'\n  , P_PRIORITY =&gt; 0\n  , P_ETAG_TYPE =&gt; 'HASH'\n  );\n  COMMIT;\nEND;\n\/\n\nBEGIN\n  ORDS.DEFINE_HANDLER(\n    P_MODULE_NAME =&gt; 'wind_turbines'\n  , P_PATTERN =&gt; 'vt\/:z\/:x\/:y'\n  , P_METHOD =&gt; 'GET'\n  , P_SOURCE_TYPE =&gt; ORDS.SOURCE_TYPE_MEDIA\n  , P_SOURCE =&gt; 'SELECT ''application\/vnd.mapbox-vector-tile'' AS mediatype\n       ,SDO_UTIL.GET_VECTORTILE(\n          TABLE_NAME =&gt; ''EXISTING_WIND_TURBINES''\n         ,GEOM_COL_NAME =&gt; ''GEOMETRY''\n         ,ATT_COL_NAMES =&gt; SDO_STRING_ARRAY(''USGS_CASE_ID'',''FIPS'',''COUNTY''\n            ,''STATE_ABBR'',''TURBINE_TOTAL_HEIGHT'',''TURBINE_CAPACITY''\n            ,''LATITUDE'',''LONGITUDE'')\n         ,TILE_X =&gt; :x\n         ,TILE_Y_PBF =&gt; :y\n         ,TILE_ZOOM =&gt; :z) AS vtile\n      FROM DUAL'\n  , P_ITEMS_PER_PAGE =&gt; 50\n  );\n  COMMIT;\nEND;\n\/<\/pre><\/div>\n\n\n\n<p><strong><em>Figure 7. <code>ORDS REST API<\/code> Module, Template, and Handler for E<code>XISTING_WIND_TURBINES<\/code> Vector Tiles<\/em><\/strong><\/p>\n\n\n\n<p>The <code>ORDS<\/code> module and template code is pretty simple, but the <code>ORDS<\/code> handler code is a bit trickier to understand, so let\u2019s take a closer look:<\/p>\n\n\n<div class=\"block-core-list\">\n<ul class=\"wp-block-list\">\n<li> I\u2019ve set <code>P_SOURCE_TYPE<\/code> to <code>ORDS.SOURCE_TYPE_MEDIA<\/code>.This tells ORDS to return the result set in binary format that also includes an accompanying <code>HTTP Content-Type<\/code> header. <\/li>\n\n\n\n<li> The code in <code>P_SOURCE<\/code> uses a <code>GET_VECTORTILE<\/code> query that will return the latitude, longitude, and other metadata for each wind turbine. <\/li>\n\n\n\n<li> Note the column I\u2019ve labeled <code>mediatype<\/code> is set to a static value of <code>application\/vnd.mapbox-vector-tile<\/code>. That matches the expected output of the vector tile binary result set. <\/li>\n<\/ul>\n<\/div>\n\n\n<p>The query also expects three bind variable values to be supplied during execution:<\/p>\n\n\n<div class=\"block-core-list\">\n<ul class=\"wp-block-list\">\n<li><code>TILE_ZOOM<\/code> determines the actual number of tiles needed to divide up a map into smaller and smaller pieces. As the value of <code>TILE_ZOOM<\/code> increases, so do the number of tiles \u2026 and thus finer and finer detail can be retrieved and displayed. If I specify <code>TILE_ZOOM<\/code> as four (4), the map would be divvied up into 2<sup>4 <\/sup>x<sup> <\/sup>2<sup>4<\/sup> tiles, or 256 (16 x 16) tiles; if it\u2019s set to eight (8), the map would be cut up into 65,536 individual tiles. <\/li>\n\n\n\n<li><code>TILE_X<\/code> defines the starting X coordinate of the grid of vector tiles to be fetched. <\/li>\n\n\n\n<li> Lastly, <code>TILE_Y_PBF<\/code> defines the Y coordinate within the grid of tiles we want to fetch. The reason we\u2019re using this format of the Y coordinate? It refers to the name of the <em>proto-buffer file<\/em> (PBF) that will be retrieved and displayed as the base layer of the map when the corresponding mapping points are displayed above that base layer. <\/li>\n<\/ul>\n<\/div>\n\n\n<h2 class=\"wp-block-heading\" id=\"h-enabling-vector-tile-displays-with-maplibre-gl\">Enabling Vector Tile Displays with MapLibre GL<\/h2>\n\n\n\n<p>While I could use Oracle Spatial Studio to map vector tiles, it takes some extra time to configure a user account and set up all the metadata and infrastructure to leverage that powerful toolset. Here\u2019s a slightly faster method I can use as a touchstone to verify that I\u2019ve set up my Oracle 23ai database-side code properly for mapping purposes with easy-to-understand HTML:<\/p>\n\n\n<div class=\"block-core-list\">\n<ul class=\"wp-block-list\">\n<li> I\u2019ll leverage Microsoft Visual Studio\u2019s <em>Live Server<\/em> browser extension to display them within an HTML frame using the <a href=\"https:\/\/maplibre.org\/\">MapLibre<\/a> <a href=\"https:\/\/github.com\/maplibre\/maplibre-gl-js\">GL JS library<\/a>. <\/li>\n\n\n\n<li> The first section of the HTML sample code in <strong>Figure<\/strong> <strong>8<\/strong> handles map server parameters for displaying the map itself, including a base map style. Here, I\u2019ve used the Open Street Map (OSM) \u201cBright\u201d style, but there are <a href=\"https:\/\/maps.oracle.com\/elocation\/mapstyles.html\">several other OSM styles available<\/a>. <\/li>\n\n\n\n<li> I\u2019ve also specified a closer initial zoom level (4) for the map and focused the initial center of the map (longitude -90 degrees, latitude 43 degrees) near south-central Wisconsin in the United States. <\/li>\n<\/ul>\n<\/div>\n\n\n<figure class=\"wp-block-image\"><img loading=\"lazy\" decoding=\"async\" width=\"801\" height=\"703\" src=\"https:\/\/www.red-gate.com\/simple-talk\/wp-content\/uploads\/2025\/06\/word-image-107053-4.png\" alt=\"\" class=\"wp-image-107057\" srcset=\"https:\/\/www.red-gate.com\/simple-talk\/wp-content\/uploads\/2025\/06\/word-image-107053-4.png 801w, https:\/\/www.red-gate.com\/simple-talk\/wp-content\/uploads\/2025\/06\/word-image-107053-4-300x263.png 300w, https:\/\/www.red-gate.com\/simple-talk\/wp-content\/uploads\/2025\/06\/word-image-107053-4-768x674.png 768w\" sizes=\"auto, (max-width: 801px) 100vw, 801px\" \/><\/figure>\n\n\n\n<p><\/p>\n\n\n\n<p><strong><em>Figure 8. MapLibre Live Server Demonstration: Initialization &amp; Setup<\/em><\/strong><\/p>\n\n\n\n<p>The rest of the HTML body is where the real magic of vector tiles shines through. In <strong>Figure 8<\/strong>,<strong> <\/strong>I\u2019ve highlighted the code that builds that handles mapping all of the existing wind turbine points:<\/p>\n\n\n<div class=\"block-core-list\">\n<ul class=\"wp-block-list\">\n<li> The code in the <strong>red<\/strong> box accesses the ORDS endpoint for the existing wind turbines I created in <strong>Figure 7<\/strong>. It works in concert with the MapLibreGL interface to shift the display to exactly the contents of the vector tiles at the corresponding <em>zoom level <\/em>for the corresponding<em> X and Y coordinates.<\/em> <\/li>\n\n\n\n<li> The code in the <strong>blue<\/strong> box specifies how each wind turbine\u2019s <em>point<\/em> should be displayed on the map. To differentiate them from other points in other layers, I\u2019ve selected I\u2019m displaying each turbine as a small green circle with a slightly darker green outline. <\/li>\n\n\n\n<li> And the code in the <strong>green<\/strong> box? It grabs the related metadata for the map point that I\u2019ve clicked on, formats it into a character string, and displays it as a pop-up. This gives me the ability to drill into specific wind turbine characteristics \u2013 in this case, its unique identifier, the state and FIPS code where it\u2019s located, and the turbine\u2019s height and generation capacity in KW. <\/li>\n\n\n\n<li> <img loading=\"lazy\" decoding=\"async\" width=\"1050\" height=\"921\" class=\"wp-image-107058\" src=\"https:\/\/www.red-gate.com\/simple-talk\/wp-content\/uploads\/2025\/06\/word-image-107053-5.png\" srcset=\"https:\/\/www.red-gate.com\/simple-talk\/wp-content\/uploads\/2025\/06\/word-image-107053-5.png 1050w, https:\/\/www.red-gate.com\/simple-talk\/wp-content\/uploads\/2025\/06\/word-image-107053-5-300x263.png 300w, https:\/\/www.red-gate.com\/simple-talk\/wp-content\/uploads\/2025\/06\/word-image-107053-5-1024x898.png 1024w, https:\/\/www.red-gate.com\/simple-talk\/wp-content\/uploads\/2025\/06\/word-image-107053-5-768x674.png 768w\" sizes=\"auto, (max-width: 1050px) 100vw, 1050px\" \/> <\/li>\n<\/ul>\n<\/div>\n\n\n<p><strong><em>Figure 9. MapLibre Live Server Demonstration: Adding a Map Layer<\/em><\/strong><\/p>\n\n\n\n<h2 class=\"wp-block-heading\" id=\"h-the-end-result-blazingly-fast-map-displays\">The End Result? Blazingly Fast Map Displays.<\/h2>\n\n\n\n<p>As much as I love using APEX Native Map Regions, I was thrilled to see that displaying map points with vector tiles and MapLibreGL is at least an order of magnitude faster \u2026 and I\u2019m running my tests on a low-cost, underpowered ASUS VivoBook laptop without any display accelerators or GPUs. I was able to traverse, zoom in, zoom out, and navigate within the map frame with significantly less lag time.<\/p>\n\n\n\n<p>And I saw no degradation in performance when I added two more mapping layers \u2013 existing photovoltaic arrays and existing EV charging stations \u2013 to my mapping configuration. <strong>Figure 10<\/strong> shows the result, with EV chargers shown in blue and PV arrays shown in red within the continental the United States.<\/p>\n\n\n\n<figure class=\"wp-block-image\"><img loading=\"lazy\" decoding=\"async\" width=\"895\" height=\"497\" src=\"https:\/\/www.red-gate.com\/simple-talk\/wp-content\/uploads\/2025\/06\/word-image-107053-6.png\" alt=\"\" class=\"wp-image-107059\" srcset=\"https:\/\/www.red-gate.com\/simple-talk\/wp-content\/uploads\/2025\/06\/word-image-107053-6.png 895w, https:\/\/www.red-gate.com\/simple-talk\/wp-content\/uploads\/2025\/06\/word-image-107053-6-300x167.png 300w, https:\/\/www.red-gate.com\/simple-talk\/wp-content\/uploads\/2025\/06\/word-image-107053-6-768x426.png 768w\" sizes=\"auto, (max-width: 895px) 100vw, 895px\" \/><\/figure>\n\n\n\n<p><br>  <br><strong><em>Figure10. Vector Tile Maps: Wide-Area Map Display<\/em><\/strong><\/p>\n\n\n\n<p><strong>Figure 11<\/strong> shows the upper Midwest of the USA at a lower zoom level. Note that individual points are still quite clearly displayed even at this zoom level.<\/p>\n\n\n\n<figure class=\"wp-block-image\"><img loading=\"lazy\" decoding=\"async\" width=\"870\" height=\"735\" src=\"https:\/\/www.red-gate.com\/simple-talk\/wp-content\/uploads\/2025\/06\/word-image-107053-7.png\" alt=\"\" class=\"wp-image-107060\" srcset=\"https:\/\/www.red-gate.com\/simple-talk\/wp-content\/uploads\/2025\/06\/word-image-107053-7.png 870w, https:\/\/www.red-gate.com\/simple-talk\/wp-content\/uploads\/2025\/06\/word-image-107053-7-300x253.png 300w, https:\/\/www.red-gate.com\/simple-talk\/wp-content\/uploads\/2025\/06\/word-image-107053-7-768x649.png 768w\" sizes=\"auto, (max-width: 870px) 100vw, 870px\" \/><\/figure>\n\n\n\n<p><\/p>\n\n\n\n<p><em><strong>Figure 11. Vector Tile Maps: Drilling Down to Lower Levels of Detail<\/strong><\/em><\/p>\n\n\n\n<p>Finally, <strong>Figure 12 <\/strong>shows an example of drilling down deeply into the map and then showing some of the metadata for one of the hundreds of thousands of map points \u2013 in this case, a single wind turbine in middle of Minnesota.<\/p>\n\n\n\n<figure class=\"wp-block-image\"><img loading=\"lazy\" decoding=\"async\" width=\"683\" height=\"410\" src=\"https:\/\/www.red-gate.com\/simple-talk\/wp-content\/uploads\/2025\/06\/word-image-107053-8.png\" alt=\"\" class=\"wp-image-107061\" srcset=\"https:\/\/www.red-gate.com\/simple-talk\/wp-content\/uploads\/2025\/06\/word-image-107053-8.png 683w, https:\/\/www.red-gate.com\/simple-talk\/wp-content\/uploads\/2025\/06\/word-image-107053-8-300x180.png 300w\" sizes=\"auto, (max-width: 683px) 100vw, 683px\" \/><\/figure>\n\n\n\n<p><\/p>\n\n\n\n<p><em><strong>Figure 12. Vector Tile Maps: Zooming In Even Lower<\/strong><\/em><\/p>\n\n\n\n<h2 class=\"wp-block-heading\" id=\"h-enough-tiling-already-what-s-coming-next\">Enough Tiling Already! What\u2019s Coming Next?<\/h2>\n\n\n\n<p>Vector tiles are just half of the new mapping capabilities that the Oracle 23ai converged database provides for your IT organization\u2019s mapping requirements. They\u2019re relatively simple to implement if you\u2019ve already embraced the SDO_GEOMETRY datatype for geospatial applications, and they\u2019re also likely to rescue your DevOps team from painful experiments with different geospatial databases.<\/p>\n\n\n\n<p>In the <a href=\"PLACEHOLDER_NextArticle.html\">next article<\/a> in this series, we\u2019ll look at how <em>Hierarchical Hexagonal Indexing<\/em> (<strong>H3<\/strong>) features in Oracle 23ai handle another type of mapping problem: visually <em>aggregating<\/em> the data that\u2019s often implicitly attached to hordes of individual geographic points so we can provide meaningfulness at any zoom level.<\/p>\n\n\n\n<h2 class=\"wp-block-heading\" id=\"h-appendix\">Appendix<\/h2>\n\n\n\n<p>If you\u2019d like to experiment with the APEX 24.2 app and the MapBox examples presented to see the dramatic difference in performance, you can download all application code samples, DDL to create tables and spatial indexes, and GIS datasets themselves <a href=\"https:\/\/www.red-gate.com\/simple-talk\/wp-content\/uploads\/2025\/06\/Part1_CodeBase.zip\" target=\"_blank\" rel=\"noreferrer noopener\">here<\/a>.<strong> <\/strong><\/p>\n\n\n\n<p><\/p>\n","protected":false},"excerpt":{"rendered":"<p>Oracle Database 23ai added 300+ new features like the new VECTOR datatype that get most of the attention, but often overlooked are two new features that dramatically expand support for complex geospatial problem-solving. In this article we\u2019ll take a closer look at vector tiling \u2013 a toolset that already has everything your developers need to&#8230;&hellip;<\/p>\n","protected":false},"author":346239,"featured_media":107065,"comment_status":"open","ping_status":"closed","sticky":false,"template":"","format":"standard","meta":{"_acf_changed":false,"footnotes":""},"categories":[143533],"tags":[4459,159331],"coauthors":[159330],"class_list":["post-107053","post","type-post","status-publish","format-standard","has-post-thumbnail","hentry","category-oracle-databases","tag-oracle","tag-oracle-vector-tiles"],"acf":[],"_links":{"self":[{"href":"https:\/\/www.red-gate.com\/simple-talk\/wp-json\/wp\/v2\/posts\/107053","targetHints":{"allow":["GET"]}}],"collection":[{"href":"https:\/\/www.red-gate.com\/simple-talk\/wp-json\/wp\/v2\/posts"}],"about":[{"href":"https:\/\/www.red-gate.com\/simple-talk\/wp-json\/wp\/v2\/types\/post"}],"author":[{"embeddable":true,"href":"https:\/\/www.red-gate.com\/simple-talk\/wp-json\/wp\/v2\/users\/346239"}],"replies":[{"embeddable":true,"href":"https:\/\/www.red-gate.com\/simple-talk\/wp-json\/wp\/v2\/comments?post=107053"}],"version-history":[{"count":11,"href":"https:\/\/www.red-gate.com\/simple-talk\/wp-json\/wp\/v2\/posts\/107053\/revisions"}],"predecessor-version":[{"id":107146,"href":"https:\/\/www.red-gate.com\/simple-talk\/wp-json\/wp\/v2\/posts\/107053\/revisions\/107146"}],"wp:featuredmedia":[{"embeddable":true,"href":"https:\/\/www.red-gate.com\/simple-talk\/wp-json\/wp\/v2\/media\/107065"}],"wp:attachment":[{"href":"https:\/\/www.red-gate.com\/simple-talk\/wp-json\/wp\/v2\/media?parent=107053"}],"wp:term":[{"taxonomy":"category","embeddable":true,"href":"https:\/\/www.red-gate.com\/simple-talk\/wp-json\/wp\/v2\/categories?post=107053"},{"taxonomy":"post_tag","embeddable":true,"href":"https:\/\/www.red-gate.com\/simple-talk\/wp-json\/wp\/v2\/tags?post=107053"},{"taxonomy":"author","embeddable":true,"href":"https:\/\/www.red-gate.com\/simple-talk\/wp-json\/wp\/v2\/coauthors?post=107053"}],"curies":[{"name":"wp","href":"https:\/\/api.w.org\/{rel}","templated":true}]}}