]> git.openstreetmap.org Git - nominatim.git/blob - docs/admin/Migration.md
333c24778eef2b577b770d822df01c61eac71166
[nominatim.git] / docs / admin / Migration.md
1 # Database Migrations
2
3 This page describes database migrations necessary to update existing databases
4 to newer versions of Nominatim.
5
6 SQL statements should be executed from the PostgreSQL commandline. Execute
7 `psql nominatim` to enter command line mode.
8
9 ## 3.6.0 -> master
10
11 ### Status table contains now time zone information
12
13 The `import_status` table has been changed to include timezone information
14 with the time stamp. You need to alter an existing table before running
15 any replication functions with:
16
17 ```sql
18 ALTER TABLE import_status ALTER COLUMN lastimportdate TYPE timestamp with time zone;
19 ```
20
21 ### New location for data files
22
23 External data files for Wikipedia importance, postcodes etc. are no longer
24 expected to reside in the source tree by default. Instead they will be searched
25 in the project directory. If you have an automated setup script you must
26 either adapt the download location or explicitly set the location of the
27 files to the old place in your `.env`.
28
29 ### Introducing `nominatim` command line tool
30
31 The various php utilities have been replaced with a single `nominatim`
32 command line tool. Make sure to adapt any scripts. There is no direct 1:1
33 matching between the old utilities and the commands of nominatim CLI. The
34 following list gives you a list of nominatim sub-commands that contain
35 functionality of each script:
36
37 * ./utils/setup.php: `import`, `freeze`, `refresh`
38 * ./utils/update.php: `replication`, `add-data`, `index`, `refresh`
39 * ./utils/specialphrases.php: `special-phrases`
40 * ./utils/check_import_finished.php: `check-database`
41 * ./utils/warm.php: `warm`
42 * ./utils/export.php: `export`
43
44 Try `nominatim <command> --help` for more information about each subcommand.
45
46 `./utils/query.php` no longer exists in its old form. `nominatim search`
47 provides a replacement but returns different output.
48
49 ## 3.5.0 -> 3.6.0
50
51 ### Change of layout of search_name_* tables
52
53 The table need a different index for nearest place lookup. Recreate the
54 indexes using the following shell script:
55
56 ```bash
57 for table in `psql -d nominatim -c "SELECT tablename FROM pg_tables WHERE tablename LIKE 'search_name_%'" -tA | grep -v search_name_blank`;
58 do
59     psql -d nominatim -c "DROP INDEX idx_${table}_centroid_place; CREATE INDEX idx_${table}_centroid_place ON ${table} USING gist (centroid) WHERE ((address_rank >= 2) AND (address_rank <= 25)); DROP INDEX idx_${table}_centroid_street; CREATE INDEX idx_${table}_centroid_street ON ${table} USING gist (centroid) WHERE ((address_rank >= 26) AND (address_rank <= 27))";
60 done
61 ```
62
63 ### Removal of html output
64
65 The debugging UI is no longer directly provided with Nominatim. Instead we
66 now provide a simple Javascript application. Please refer to
67 [Setting up the Nominatim UI](../Setup-Nominatim-UI) for details on how to
68 set up the UI.
69
70 The icons served together with the API responses have been moved to the
71 nominatim-ui project as well. If you want to keep the `icon` field in the
72 response, you need to set `CONST_MapIcon_URL` to the URL of the `/mapicon`
73 directory of nominatim-ui.
74
75 ### Change order during indexing
76
77 When reindexing places during updates, there is now a different order used
78 which needs a different database index. Create it with the following SQL command:
79
80 ```sql
81 CREATE INDEX idx_placex_pendingsector_rank_address
82   ON placex
83   USING BTREE (rank_address, geometry_sector)
84   WHERE indexed_status > 0;
85 ```
86
87 You can then drop the old index with:
88
89 ```sql
90 DROP INDEX idx_placex_pendingsector;
91 ```
92
93 ### Unused index
94
95 This index has been unused ever since the query using it was changed two years ago. Saves about 12GB on a planet installation.
96
97 ```sql
98 DROP INDEX idx_placex_geometry_reverse_lookupPoint;
99 ```
100
101 ### Switching to dotenv
102
103 As part of the work changing the configuration format, the configuration for
104 the website is now using a separate configuration file. To create the
105 configuration file, run the following command after updating:
106
107 ```sh
108 ./utils/setup.php --setup-website
109 ```
110
111 ## 3.4.0 -> 3.5.0
112
113 ### New Wikipedia/Wikidata importance tables
114
115 The `wikipedia_*` tables have a new format that also includes references to
116 Wikidata. You need to update the computation functions and the tables as
117 follows:
118
119   * download the new Wikipedia tables as described in the import section
120   * reimport the tables: `./utils/setup.php --import-wikipedia-articles`
121   * update the functions: `./utils/setup.php --create-functions --enable-diff-updates`
122   * create a new lookup index:
123 ```sql
124 CREATE INDEX idx_placex_wikidata
125   ON placex
126   USING BTREE ((extratags -> 'wikidata'))
127   WHERE extratags ? 'wikidata'
128     AND class = 'place'
129     AND osm_type = 'N'
130     AND rank_search < 26;
131 ```
132   * compute importance: `./utils/update.php --recompute-importance`
133
134 The last step takes about 10 hours on the full planet.
135
136 Remove one function (it will be recreated in the next step):
137
138 ```sql
139 DROP FUNCTION create_country(hstore,character varying);
140 ```
141
142 Finally, update all SQL functions:
143
144 ```sh
145 ./utils/setup.php --create-functions --enable-diff-updates --create-partition-functions
146 ```
147
148 ## 3.3.0 -> 3.4.0
149
150 ### Reorganisation of location_area_country table
151
152 The table `location_area_country` has been optimized. You need to switch to the
153 new format when you run updates. While updates are disabled, run the following
154 SQL commands:
155
156 ```sql
157 CREATE TABLE location_area_country_new AS
158   SELECT place_id, country_code, geometry FROM location_area_country;
159 DROP TABLE location_area_country;
160 ALTER TABLE location_area_country_new RENAME TO location_area_country;
161 CREATE INDEX idx_location_area_country_geometry ON location_area_country USING GIST (geometry);
162 CREATE INDEX idx_location_area_country_place_id ON location_area_country USING BTREE (place_id);
163 ```
164
165 Finally, update all SQL functions:
166
167 ```sh
168 ./utils/setup.php --create-functions --enable-diff-updates --create-partition-functions
169 ```
170
171 ## 3.2.0 -> 3.3.0
172
173 ### New database connection string (DSN) format
174
175 Previously database connection setting (`CONST_Database_DSN` in `settings/*.php`) had the format
176
177    * (simple) `pgsql://@/nominatim`
178    * (complex) `pgsql://johndoe:secret@machine1.domain.com:1234/db1`
179
180 The new format is
181
182    * (simple) `pgsql:dbname=nominatim`
183    * (complex) `pgsql:dbname=db1;host=machine1.domain.com;port=1234;user=johndoe;password=secret`
184
185 ### Natural Earth country boundaries no longer needed as fallback
186
187 ```sql
188 DROP TABLE country_naturalearthdata;
189 ```
190
191 Finally, update all SQL functions:
192
193 ```sh
194 ./utils/setup.php --create-functions --enable-diff-updates --create-partition-functions
195 ```
196
197 ### Configurable Address Levels
198
199 The new configurable address levels require a new table. Create it with the
200 following command:
201
202 ```sh
203 ./utils/update.php --update-address-levels
204 ```
205
206 ## 3.1.0 -> 3.2.0
207
208 ### New reverse algorithm
209
210 The reverse algorithm has changed and requires new indexes. Run the following
211 SQL statements to create the indexes:
212
213 ```sql
214 CREATE INDEX idx_placex_geometry_reverse_lookupPoint
215   ON placex
216   USING gist (geometry)
217   WHERE (name IS NOT null or housenumber IS NOT null or rank_address BETWEEN 26 AND 27)
218     AND class NOT IN ('railway','tunnel','bridge','man_made')
219     AND rank_address >= 26
220     AND indexed_status = 0
221     AND linked_place_id IS null;
222 CREATE INDEX idx_placex_geometry_reverse_lookupPolygon
223   ON placex USING gist (geometry)
224   WHERE St_GeometryType(geometry) in ('ST_Polygon', 'ST_MultiPolygon')
225     AND rank_address between 4 and 25
226     AND type != 'postcode'
227     AND name is not null
228     AND indexed_status = 0
229     AND linked_place_id is null;
230 CREATE INDEX idx_placex_geometry_reverse_placeNode
231   ON placex USING gist (geometry)
232   WHERE osm_type = 'N'
233     AND rank_search between 5 and 25
234     AND class = 'place'
235     AND type != 'postcode'
236     AND name is not null
237     AND indexed_status = 0
238     AND linked_place_id is null;
239 ```
240
241 You also need to grant the website user access to the `country_osm_grid` table:
242
243 ```sql
244 GRANT SELECT ON table country_osm_grid to "www-user";
245 ```
246
247 Replace the `www-user` with the user name of your website server if necessary.
248
249 You can now drop the unused indexes:
250
251 ```sql
252 DROP INDEX idx_placex_reverse_geometry;
253 ```
254
255 Finally, update all SQL functions:
256
257 ```sh
258 ./utils/setup.php --create-functions --enable-diff-updates --create-partition-functions
259 ```
260
261 ## 3.0.0 -> 3.1.0
262
263 ### Postcode Table
264
265 A new separate table for artificially computed postcode centroids was introduced.
266 Migration to the new format is possible but **not recommended**.
267
268 Create postcode table and indexes, running the following SQL statements:
269
270 ```sql
271 CREATE TABLE location_postcode
272   (place_id BIGINT, parent_place_id BIGINT, rank_search SMALLINT,
273    rank_address SMALLINT, indexed_status SMALLINT, indexed_date TIMESTAMP,
274    country_code varchar(2), postcode TEXT,
275    geometry GEOMETRY(Geometry, 4326));
276 CREATE INDEX idx_postcode_geometry ON location_postcode USING GIST (geometry);
277 CREATE UNIQUE INDEX idx_postcode_id ON location_postcode USING BTREE (place_id);
278 CREATE INDEX idx_postcode_postcode ON location_postcode USING BTREE (postcode);
279 GRANT SELECT ON location_postcode TO "www-data";
280 DROP TYPE IF EXISTS nearfeaturecentr CASCADE;
281 CREATE TYPE nearfeaturecentr AS (
282   place_id BIGINT,
283   keywords int[],
284   rank_address smallint,
285   rank_search smallint,
286   distance float,
287   isguess boolean,
288   postcode TEXT,
289   centroid GEOMETRY
290 );
291 ```
292
293 Add postcode column to `location_area` tables with SQL statement:
294
295 ```sql
296 ALTER TABLE location_area ADD COLUMN postcode TEXT;
297 ```
298
299 Then reimport the functions:
300
301 ```sh
302 ./utils/setup.php --create-functions --enable-diff-updates --create-partition-functions
303 ```
304
305 Create appropriate triggers with SQL:
306
307 ```sql
308 CREATE TRIGGER location_postcode_before_update BEFORE UPDATE ON location_postcode
309     FOR EACH ROW EXECUTE PROCEDURE postcode_update();
310 ```
311
312 Finally populate the postcode table (will take a while):
313
314 ```sh
315 ./utils/setup.php --calculate-postcodes --index --index-noanalyse
316 ```
317
318 This will create a working database. You may also delete the old artificial
319 postcodes now. Note that this may be expensive and is not absolutely necessary.
320 The following SQL statement will remove them:
321
322 ```sql
323 DELETE FROM place_addressline a USING placex p
324  WHERE a.address_place_id = p.place_id and p.osm_type = 'P';
325 ALTER TABLE placex DISABLE TRIGGER USER;
326 DELETE FROM placex WHERE osm_type = 'P';
327 ALTER TABLE placex ENABLE TRIGGER USER;
328 ```