Index data from Azure Database for MySQL flexible server
In this article, learn how to configure an indexer that imports content from Azure Database for MySQL and makes it searchable in Azure AI Search. Inputs to the indexer are your row, in a single table or view. Output is a search index with searchable content in individual fields.
This article supplements Create an indexer with information that's specific to indexing from Azure Database for MySQL flexible server. It uses the REST APIs to demonstrate a three-part workflow common to all indexers: create a data source, create an index, create an indexer. Data extraction occurs when you submit the Create Indexer request.
When configured to include a high water mark and soft deletion, the indexer takes all changes, uploads, and deletes for your MySQL database. It reflects these changes in your search index. Data extraction occurs when you submit the Create Indexer request.
Prerequisites
Register for the preview to provide scenario feedback. You can access the feature automatically after form submission.
Azure Database for MySQL flexible server and sample data. Data must reside in a table or view. A primary key is required. If you're using a view, it must have a high water mark column.
Read permissions. A full access connection string includes a key that grants access to the content, but if you're using Azure roles, make sure the search service managed identity has Reader permissions on MySQL.
A REST client to create the data source, index, and indexer.
You can also use the Azure SDK for .NET. You can't use the portal for indexer creation, but you can manage indexers and data sources once they're created.
Preview limitations
Currently, change tracking and deletion detection aren't working if the date or timestamp is uniform for all rows. This limitation is a known issue to be addressed in an update to the preview. Until this issue is addressed, don't add a skillset to the MySQL indexer.
The preview doesn't support geometry types and blobs.
As noted, there's no portal support for indexer creation, but a MySQL indexer and data source can be managed in the portal once they exist. For example, you can edit the definitions, and reset, run, or schedule the indexer.
Define the data source
The data source definition specifies the data to index, credentials, and policies for identifying changes in the data. The data source is defined as an independent resource so that it can be used by multiple indexers.
Create or Update Data Source specifies the definition. Be sure to use a preview REST API when creating the data source.
POST https://[search service name].search.azure.cn/datasources?api-version=2020-06-30-Preview
Content-Type: application/json
api-key: [admin key]
{
"name" : "hotel-mysql-ds",
"description" : "[Description of MySQL data source]",
"type" : "mysql",
"credentials" : {
"connectionString" :
"Server=[MySQLServerName].MySQL.database.azure.com; Port=3306; Database=[DatabaseName]; Uid=[UserName]; Pwd=[Password]; SslMode=Preferred;"
},
"container" : {
"name" : "[TableName]"
},
"dataChangeDetectionPolicy" : {
"@odata.type": "#Microsoft.Azure.Search.HighWaterMarkChangeDetectionPolicy",
"highWaterMarkColumnName": "[HighWaterMarkColumn]"
}
}
Key points:
Set
type
to"mysql"
(required).Set
credentials
to an ADO.NET connection string. You can find connection strings in Azure portal, on the Connection strings page for MySQL.Set
container
to the name of the table.Set
dataChangeDetectionPolicy
if data is volatile and you want the indexer to pick up just the new and updated items on subsequent runs.Set
dataDeletionDetectionPolicy
if you want to remove search documents from a search index when the source item is deleted.
Create an index
Create or Update Index specifies the index schema:
{
"name" : "hotels-mysql-ix",
"fields": [
{ "name": "ID", "type": "Edm.String", "key": true, "searchable": false },
{ "name": "HotelName", "type": "Edm.String", "searchable": true, "filterable": false },
{ "name": "Category", "type": "Edm.String", "searchable": false, "filterable": true, "sortable": true },
{ "name": "City", "type": "Edm.String", "searchable": false, "filterable": true, "sortable": true },
{ "name": "Description", "type": "Edm.String", "searchable": false, "filterable": false, "sortable": false }
]
}
If the primary key in the source table matches the document key (in this case, "ID"), the indexer imports the primary key as the document key.
Mapping data types
The following table maps the MySQL database to Azure AI Search equivalents. For more information, see Supported data types (Azure AI Search).
Note
The preview does not support geometry types and blobs.
MySQL data types | Azure AI Search field types |
---|---|
bool , boolean |
Edm.Boolean, Edm.String |
tinyint , smallint , mediumint , int , integer , year |
Edm.Int32, Edm.Int64, Edm.String |
bigint |
Edm.Int64, Edm.String |
float , double , real |
Edm.Double, Edm.String |
date , datetime , timestamp |
Edm.DateTimeOffset, Edm.String |
char , varchar , tinytext , mediumtext , text , longtext , enum , set , time |
Edm.String |
unsigned numerical data, serial, decimal, dec, bit, blob, binary, geometry | N/A |
Configure and run the MySQL indexer
Once the index and data source have been created, you're ready to create the indexer. Indexer configuration specifies the inputs, parameters, and properties controlling run time behaviors.
Create or update an indexer by giving it a name and referencing the data source and target index:
POST https://[search service name].search.azure.cn/indexers?api-version=2020-06-30
{
"name" : "hotels-mysql-idxr",
"dataSourceName" : "hotels-mysql-ds",
"targetIndexName" : "hotels-mysql-ix",
"disabled": null,
"schedule": null,
"parameters": {
"batchSize": null,
"maxFailedItems": null,
"maxFailedItemsPerBatch": null,
"base64EncodeKeys": null,
"configuration": { }
},
"fieldMappings" : [ ],
"encryptionKey": null
}
Key points:
Specify field mappings if there are differences in field name or type, or if you need multiple versions of a source field in the search index.
An indexer runs automatically when it's created. You can prevent it from running by setting
disabled
totrue
. To control indexer execution, run an indexer on demand or put it on a schedule.
Check indexer status
Send a Get Indexer Status request to monitor indexer execution:
GET https://myservice.search.azure.cn/indexers/myindexer/status?api-version=2024-05-01-preview
Content-Type: application/json
api-key: [admin key]
The response includes status and the number of items processed. It should look similar to the following example:
{
"status":"running",
"lastResult": {
"status":"success",
"errorMessage":null,
"startTime":"2024-02-21T00:23:24.957Z",
"endTime":"2024-02-21T00:36:47.752Z",
"errors":[],
"itemsProcessed":1599501,
"itemsFailed":0,
"initialTrackingState":null,
"finalTrackingState":null
},
"executionHistory":
[
{
"status":"success",
"errorMessage":null,
"startTime":"2024-02-21T00:23:24.957Z",
"endTime":"2024-02-21T00:36:47.752Z",
"errors":[],
"itemsProcessed":1599501,
"itemsFailed":0,
"initialTrackingState":null,
"finalTrackingState":null
},
... earlier history items
]
}
Execution history contains up to 50 of the most recently completed executions, which are sorted in the reverse chronological order so that the latest execution comes first.
Indexing new and changed rows
Once an indexer has fully populated a search index, you might want subsequent indexer runs to incrementally index just the new and changed rows in your database.
To enable incremental indexing, set the dataChangeDetectionPolicy
property in your data source definition. This property tells the indexer which change tracking mechanism is used on your data.
For Azure Database for MySQL indexers, the only supported policy is the HighWaterMarkChangeDetectionPolicy
.
An indexer's change detection policy relies on having a high water mark column that captures the row version, or the date and time when a row was last updated. It's often a DATE
, DATETIME
, or TIMESTAMP
column at a granularity sufficient for meeting the requirements of a high water mark column.
In your MySQL database, the high water mark column must meet the following requirements:
- All data inserts must specify a value for the column.
- All updates to an item also change the value of the column.
- The value of this column increases with each insert or update.
- Queries with the following
WHERE
andORDER BY
clauses can be executed efficiently:WHERE [High Water Mark Column] > [Current High Water Mark Value] ORDER BY [High Water Mark Column]
The following example shows a data source definition with a change detection policy:
POST https://[search service name].search.azure.cn/datasources?api-version=2020-06-30-Preview
Content-Type: application/json
api-key: [admin key]
{
"name" : "[Data source name]",
"type" : "mysql",
"credentials" : { "connectionString" : "[connection string]" },
"container" : { "name" : "[table or view name]" },
"dataChangeDetectionPolicy" : {
"@odata.type" : "#Microsoft.Azure.Search.HighWaterMarkChangeDetectionPolicy",
"highWaterMarkColumnName" : "[last_updated column name]"
}
}
Important
If you're using a view, you must set a high water mark policy in your indexer data source.
If the source table does not have an index on the high water mark column, queries used by the MySQL indexer might time out. In particular, the ORDER BY [High Water Mark Column]
clause requires an index to run efficiently when the table contains many rows.
Indexing deleted rows
When rows are deleted from the table or view, you normally want to delete those rows from the search index as well. However, if the rows are physically removed from the table, an indexer has no way to infer the presence of records that no longer exist. The solution is to use a soft-delete technique to logically delete rows without removing them from the table. Add a column to your table or view and mark rows as deleted using that column.
Given a column that provides deletion state, an indexer can be configured to remove any search documents for which deletion state is set to true
. The configuration property that supports this behavior is a data deletion detection policy, which is specified in the data source definition as follows:
{
…,
"dataDeletionDetectionPolicy" : {
"@odata.type" : "#Microsoft.Azure.Search.SoftDeleteColumnDeletionDetectionPolicy",
"softDeleteColumnName" : "[a column name]",
"softDeleteMarkerValue" : "[the value that indicates that a row is deleted]"
}
}
The softDeleteMarkerValue
must be a string. For example, if you have an integer column where deleted rows are marked with the value 1, use "1"
. If you have a BIT
column where deleted rows are marked with the Boolean true value, use the string literal True
or true
(the case doesn't matter).
Next steps
You can now run the indexer, monitor status, or schedule indexer execution. The following articles apply to indexers that pull content from Azure MySQL: