Chapter 27 Using the Query Analyzer

Table of Contents

27.1 Providing Query Analyzer Data
27.1.1 Using the MySQL Performance Schema
27.2 Query Response Time index (QRTi)
27.3 Query Analyzer User Interface
27.3.1 Getting Detailed Query Information
27.3.2 Using Graphs to Identify Queries
27.3.3 Filtering Query Analyzer Data
27.3.4 Query Analyzer Settings
27.3.5 Exporting Query Information

The MySQL Query Analyzer enables you to monitor SQL statements executed on a MySQL server and see details about each query, number of executions and execution times. Similar queries with different literal values are combined for reporting purposes.

Query Analyzer collects information about SQL statements that a MySQL client application sends to the MySQL server. There are different methods that the Query Analyzer can receive this information, which are:

Once your MySQL client application is configured to communicate via the MySQL Enterprise Monitor Agent, queries are monitored and the normalized queries are sent to the MySQL Enterprise Monitor Agent.

For the different ways to enable Query Analysis, see Section 27.1, “Providing Query Analyzer Data”. For the user interface of the Query Analyzer, see Chapter 27, Using the Query Analyzer and Section 27.3, “Query Analyzer User Interface”.

Once the data is collected, you view and monitor the queries, check the execution statistics, and filter and drill down on the information. By comparing the queries to the server graphs, you can correlate query execution with server status. For more information on viewing, filtering and reporting on the Query Analyzer data, see Section 27.3, “Query Analyzer User Interface”.

Note

When MySQL Enterprise Monitor is not accessible from a Connector/J or Connector/NET query analyzer plugin, the application performance is not impacted. Over time, the plugin determines that a backlog of reportable data exists, and fall back to consolidating it over longer ranges of time. But if more than 1,000 canonical queries are being used by the application (an unlikely scenario), data is dropped.

27.1 Providing Query Analyzer Data

The MySQL Query Analyzer can be fed information from a number of different sources. The provider supplies the statistical information about the queries, execution times, result counts and other data to display and analyze on the Query Analyzer page.

There are a number of different methods available for supplying query information to MySQL Enterprise Service Manager:

  • Using the Performance Schema statement digests with MySQL Server 5.6.14 and above, data can be gathered directly from MySQL Server without additional configuration.

  • Using a MySQL connector with a corresponding MySQL Enterprise Monitor Plugin that provides tracing and statistical information directly to MySQL Enterprise Service Manager.

    Using this method requires a connector that is capable of collecting and sending the query statistical data directly to MySQL Enterprise Service Manager. The connectors collect the basic query statistics, such as the execution time for each query, and the row counts, and provide this information to MySQL Enterprise Service Manager for analysis.

    Note

    This implementation type does not require the proxy component.

  • Using the MySQL Enterprise Monitor Proxy and Aggregator. For more information, see Chapter 11, Proxy and Aggregator Installation.

    Important

    If you are using the MySQL Enterprise Monitor Proxy and Aggregator to collect query performance data, you must disable the statements_digest consumer in performance_schema.setup_consumers.

27.1.1 Using the MySQL Performance Schema

As of MySQL Enterprise Monitor 3.0.0, Query Analyzer data is automatically collected and displayed by simply monitoring MySQL Server 5.6.14 or greater, and without any additional plugins required. This ability comes from the Performance Schema Statement Digests feature (Performance Schema Statement Digests) that was added in MySQL 5.6. If you are using an earlier version of MySQL Server (5.6.13 or below), then you can continue to use a Connector Plugin or MySQL Proxy to provide performance information to the Query Analyzer.

Note

MySQL server versions prior to MySQL 5.6.14 are disabled due to a crashing bug within Statement Digests that could be triggered by collecting the data from the Agent.

Collecting Query Analyzer data from Performance Schema, rather than at the wire protocol (which is how the other sources of Query Analyzer data work) provides data about what the statements do to generate their result sets that other sources cannot provide:

  • Table Lock time

  • How many rows were examined versus returned

  • How many temporary tables were created, and whether any were created on disk

  • Whether range scans were done, and in what form they were done

  • Whether sorting happened, how many rows were sorted, and what form the sort took

There is also information not available when operating in this mode that is provided to the Query Analyzer when using Connector Plugins and MySQL Proxy:

  • Stack trace of where the statement originated from on the application side (Connector Plugins only)

  • Histograms of response times

  • Standard deviation of response times

When enabled (which is the default), the MySQL Enterprise Monitor Agent polls the performance_schema.events_statements_summary_by_digest table (every minute, by default) and continually compute the deltas for each of the normalized statements that are exposed during the snapshot window. This is dependent on the Performance Schema setup having the "statements_digest" consumer enabled within performance_schema.setup_consumers, which is enabled by default in MySQL 5.6:


mysql> SELECT * FROM performance_schema.setup_consumers WHERE name = 'statements_digest';
+-------------------+---------+
| NAME              | ENABLED |
+-------------------+---------+
| statements_digest | YES     |
+-------------------+---------+

If this is not enabled, then enable it with:


UPDATE performance_schema.setup_consumers SET enabled = 'YES' WHERE name = 'statements_digest';

Note

The MySQL Enterprise Monitor Agent does not TRUNCATE the performance_schema.events_statements_summary_by_digest table each time it reads from it, as it is possible there may be other processes/tools consuming this data. Because of this, the "Max Latency" statistic that is reported per a normalized statement within Query Analyzer is actually the maximum since either the MySQL Server started, or since a TRUNCATE TABLE performance_schema.events_statements_summary_by_digest was executed. This differs from the MySQL Proxy or Connector Plugins, which report the maximum run time per the aggregated snapshot period.

Note

The digested Performance Schema query limit is 1,024 characters in length, in that queries exceeding this length are truncated.

The performance_schema.events_statements_summary_by_digest table is a sized table in memory within the Performance Schema, and its size is auto-configured. To check the current size:


mysql> SHOW GLOBAL VARIABLES LIKE 'performance_schema_digests_size';
+---------------------------------+-------+
| Variable_name                   | Value |
+---------------------------------+-------+
| performance_schema_digests_size | 5000  |
+---------------------------------+-------+

If your application executes more than this number of normalized statements, then it is possible that you may begin losing some statement instrumentation. You can monitor this situation with the Performance_schema_digest_lost system variable:


mysql> SHOW GLOBAL STATUS LIKE 'Performance_schema_digest_lost';
+--------------------------------+-------+
| Variable_name                  | Value |
+--------------------------------+-------+
| Performance_schema_digest_lost | 0     |
+--------------------------------+-------+

If you detect that this counter variable is growing, consider increasing the performance_schema_digests_size system variable. It is also possible that your statement profile has changed over time, and that you are now executing different statements than were originally tracked (this is especially possible in very long running instances). In this case, you can simply TRUNCATE TABLE performance_schema.events_statements_summary_by_digest, and the Query Analyzer collection automatically starts again.

When the "Example Query" feature is enabled, Query Analyzer attempts to get an example of the longest running statement during the snapshot interval by doing a LEFT JOIN with a groupwise-max on the performance_schema.events_statements_summary_by_digest table to the performance_schema.events_statements_history_long table. Using this method does not guarantee that an example statement is always provided because, by default, the events_statements_history_long table is a ring buffer of the last 1000 statements executed. This too differs from the Connector Plugin and MySQL Proxy sources, which always provide an example per normalized statement, per snapshot, when enabled. We collect in this way with Performance Schema to minimize load on the monitored instance rather than polling the performance_schema.events_statements_history_long table at too high a frequently to try and gather statistics.

Note

A small subset (approximately 2MB of data) of the snapshot of known prior values is retained in-memory, and the rest is spooled to disk. The spool is stored in $MYSQL_AGENT_HOME/spool/queryAnalysis.

The "Example Query" feature requires that the events_statements_history_long table is enabled within performance_schema.setup_consumers (this is disabled by default within MySQL 5.6):


mysql> SELECT * FROM performance_schema.setup_consumers where name = 
'events_statements_history_long';
+--------------------------------+---------+
| NAME                           | ENABLED |
+--------------------------------+---------+
| events_statements_history_long | NO      |
+--------------------------------+---------+

If this is not enabled, then enable it with:


UPDATE performance_schema.setup_consumers SET enabled = 'YES' WHERE name = 
'events_statements_history_long';

When "Example Query" and "Example Explain" are enabled, the MySQL Enterprise Monitor Agent attempts to run an EXPLAIN for each example statement that is discovered and ran for longer than the "Auto-Explain Threshold". Due to the way that Performance Schema exposes normalized statements, truncating any normalized statement that is longer than 1024 bytes due to memory concerns within the MySQL Server means it is possible that an EXPLAIN may fail because the truncated statements do not parse correctly when running the EXPLAIN.

27.2 Query Response Time index (QRTi)

QRTi stands for "Query Response Time index". It is a "quality of service" measurement for each query, and uses the Apdex formula for that calculation: Apdex on Wikipedia.

How QRTi is Defined

The three measurement conditions are "optimum", "acceptable", and "unacceptable", which are defined as:

Table 27.1 QRTi value definitions

TypeDefault time valuesAssigned valueDescriptionColor
Optimum100ms1.00 (100%)The optimal time frameGreen
Acceptable4 * Optimum -- 100ms to 400ms0.50 (50%)An acceptable time frameYellow
UnacceptableExceeds Acceptable -- greater than 400ms0.00 (0%)An unacceptable time frameRed

An example calculation

From there, we calculate an average to determine the final QRTi value. For Example, if there are 100 executions of the digested/canonical query, where 60 finished below 100ms (the optimal time frame), 30 between 100ms and 400ms (the acceptable time frame), and the remaining 10 took longer than 400ms (unacceptable time), then the QRTi score is:

      ( (60 + (30 / 2) + (10*0) ) / 100) = 0.75.

Reading QRTi Values

The queries listed on the Query Analyzer page also have a color coded pie chart representing a breakdown of the values used in the QRTi calculation (green representing the optimal time frame, yellow the acceptable time frame, and red the unacceptable). You can mouse over the pie chart itself to see the total number of query executions that fell within each category, as well as the percentage of query executions that fell within that group.

So when doing query optimization, you want to start with the ones that have a QRTi visual pie chart that is 100% red, which means that they also have an actual QRTi value of 0. This means that *all* executions of that query took longer than the acceptable time frame (400ms by default). You can then click on the query to get more information, such as the maximum and average query times, the average number of rows examined, the average lock wait time, examine a sample query, look at an example EXPLAIN plan, see if full table scans were done, examine index usage, etc.

You can then work your way up from the queries with a QRTi value of 0, towards those that have a value of 1 (1 meaning that all instances of the query executed within the optimal time frame). Once you get to the point that you no longer have any queries with a QRTi value of less than 1, then you can go into the Query Analysis Reporting Advisor configuration, and adjust the QRTi Threshold (the target time) down, say to 50ms, and start the process all over again.

27.3 Query Analyzer User Interface

To analyze the queries captured by the agent/proxy, change to the Query Analyzer tab. The following figure shows an example of the table on that page:

Figure 27.1 MySQL Enterprise Monitor User Interface: Query Analyzer

MySQL Enterprise Monitor User Interface: Query Analyzer

The main Query Analyzer table provides the summary information for all of the queries executed via the agent/proxy. The table tracks all the queries submitted to the server via the agent/proxy. The table shows a maximum of 100 rows, and you can page through the list of queries by using the page numbers, or the next, previous, first, and last buttons. To filter the list of queries that are displayed, or to change the number of queries, see Section 27.3.3, “Filtering Query Analyzer Data”. To export the query information as a .csv file, see Section 27.3.5, “Exporting Query Information”.

Each row within the table provides the statistical information for one normalized query statement. If you have configured multiple agent/proxies to accept and forward queries to different servers, then you can expand the server view. The summary information displayed is different depending on whether you have selected a server group or an individual server.

If you have selected a server group, then the information displayed is aggregated from across the entire group. The same query executed on multiple servers shows average, total and minimum/maximum information for that query across all the servers. If you select an individual server, then only queries executed on that server are included within the table.

For each row, the following columns are populated according to the selected filtering options. For example, if the filter is configured to show queries within the last 30 minutes (Interval), then only queries executed during that time are displayed, and the corresponding statistics, such as execution times, rows returned and bytes returned, reflect that 30 minute timespan.

  • Query: The normalized version of the query. Normalization removes the query-specific data so that different queries with different data parameters are identified as the same basic query.

    The information is shown as one query per row. Each query row is expandable, and can be expanded to show the execution times for individual servers for that query.

  • Database: The default database in use at the time of the query. The database name might be blank, or might not match the database used within the query, if you used a qualified table name (for example, select ... from db_name.table_name) or if you issued a USE statement to switch databases after connecting.

  • Execution notices: Highlights any specific issues experienced when running queries, including excessive table scans and bad index usage. These provide an immediate indication of a problem with a query that might require additional examination.

  • Counts: The number of times that the query has been executed. The column is sub-divided into three further columns, showing the number of executions of the query (Exec), the number of times an error has been reported for the query (Err), and the number of times a warning has been produced (Warn).

  • QRTi: Lists the Query Response Time index of the query. For more information, see Section 27.2, “Query Response Time index (QRTi)”.

  • Latency (hh:mm:ss.ms): The execution time for all the matching queries. This is the time, for every invocation of the corresponding query, as calculated by comparing the time when the query was submitted and when the results were returned by the server. Times are expressed in HH:MM:SS.MS (hours, minutes, seconds, and milliseconds).

    The Exec Time column is further subdivided into the following columns:

    • Total: The cumulative execution time for all the executions of this query.

    • Max: The maximum execution time for an execution of this query.

    • Avg: The average execution time for the execution of this query.

    • Locks: the time spent waiting for table locks caused by the query.

    • Average History graph (Avg History): graphs the average execution time.

    When looking at the information provided in this query, compare the average and maximum execution times to see if there was a problem on a specific server or during a specific time period when the query took place, as this could indicate an issue that needs to be investigated.

  • Rows: The rows returned by the query. The column is sub-divided into the following columns:

    • Total: The sum total number of rows returned by all executions of the query.

    • Max: The maximum number of rows returned by a single execution of the query.

    • Avg: The average number of rows returned by all executions of the query.

  • Bytes: The number of bytes returned by each query. The column is sub-divided into the following columns:

    • Total: The sum total bytes returned by all executions of the query.

    • Max: The maximum number of bytes returned by a single execution of the query.

    • Avg: The average number of bytes returned by all executions of the query.

  • First Seen: The date and time the normalized version of this query was first seen, which might be earlier than the period specified by the filter.

You can sort the list of queries by clicking the column name. The direction of the sort (highest to lowest, or lowest to highest) is indicated by a triangle next to the currently selected column. The default is to sort the list of queries by the Latency:Total time.

To help you and locate queries you can filter the list of queries using a variety of criteria. For more information on the filtering methods available, see Section 27.3.3, “Filtering Query Analyzer Data”.

27.3.1 Getting Detailed Query Information

Click on an individual query to see more detailed information about the individual query in a pop-up window. The available tabs within this window depend on whether you have configured the more detailed query information. By default, you see the Canonical Query view.

You can also view Example Query, which provides more detailed data about a specific query, including the data and parameters submitted. You can also enable Explain Query, which lets you remotely execute an EXPLAIN statement with the specified query and view the resulting information. Finally, you can view any graph data produced during the execution of the query by using the Graphs tab.

  • The Canonical Query tab:

    The canonical view for a query provides three different views of the query, which can be changed using the links under the Canonical Form section. The truncated version is a shortened version of the query. The full version of the query is the entire query statement. Normalization removes the constants from the individual queries so that queries following the same logical structure are identified as the same basic query.

    Note

    The "full" version of statements provided by the digested Performance Schema may be truncated, as the Performance Schema statement digest may truncate the statement due to memory constraints.

    In addition to the summary information given in the table, the Execution Time Statistics section provides you with more detailed execution time statistics, including the minimum time, maximum time, average time, total time and the standard deviation. The standard deviation lets you determine whether a particular invocation of a query is outside the normal distribution of times for the given query.

    The Row Statistics provide more detailed contents on the maximum, minimum, average, total, and standard deviation for the number of rows returned by the query, and the total size and maximum size of the data returned. The time period for the total and average figures is shown under the Time Span header.

    The Execution Summary section provides the summary data available in the main table, covering the execution count, and counts of the number of errors, warnings, queries that triggered table scans, and those that indicated a bad index use.

    The First Seen reports when the normalized version of this query was first seen, whether or not this was within the indicated Time Span.

    To close the query detail window, click the Hide button.

  • The Example Query tab:

    The Example Query tab provides detailed information about the most expensive query executed, as determined by the execution time.

    In addition to the full query, with data, that was executed, the tab shows the execution time, data, user, thread ID, client host and execution host for the given query.

    For queries from any of the MySQL Enterprise Plugin for Connectors, the Source Location contains the information from the Connector where the query was generated.

  • The Explain Query tab:

    The Explain Query tab lets you view the output from running the query with the EXPLAIN prefix. For more information, see EXPLAIN Syntax.

    Important

    Explains are generated for query data supplied by the MySQL Enterprise Monitor Proxy and Aggregator, Connector/J plugin, and Performance Schema sources.

    Explain is supported for all DML statements on MySQL 5.6.3 or higher. On earlier versions, only SELECT is supported.

    Note

    If the Query Analyzer is used with the MySQL Enterprise Monitor Proxy and Aggregator, EXPLAIN is not performed for any SELECT statement which uses SQL_CALC_FOUND_ROWS.

  • The Graphs tab:

    The Graphs tab shows key graphs over the selected time period for the example query. Shown are graphs of the Execution Time, Executions, Rows, and Kilobytes. These can be used to identify deviations from the normal values. Unlike the query-correlation graphs, these graphs shown only the query statistics over the given time period.

27.3.2 Using Graphs to Identify Queries

The MySQL Enterprise Monitor User Interface supports correlated graphs so that you can compare the graphed execution parameters, such as the server load, thread statistics, or RAM usage, against the queries that were being executed by the server or servers being monitored at that time.

You can use the correlated graphs in two different ways:

  • Drag and select an area on a graph as displayed within the Overview dashboard, or from the Graphs & Reports page of the MySQL Enterprise Monitor User Interface. You can drag and select any region on a displayed graph, click the QUAN icon, and it loads the selected range into the Query Analyzer page, displaying the corresponding zoomed graph, and the associated queries being executed during the selected period.

  • Do the same, but select the graph from within the Query Analyzer page.

When using the correlated graphs, selecting an area within the graph sets the start and end time within the query filtering selection. You can combine with other filtering options, such as the Query Type, to zero in on the queries to examine.

To use the graphs in this manner, select a starting point and click, while holding down the button, drag a selection area to set the time-range for the query display. The time range that you select is displayed above the graph as you select the area.

To export the graph, see Section 18.1, “All Timeseries Graphs”.

27.3.3 Filtering Query Analyzer Data

You can filter the queries shown within the Query Analyzer table by using the form at the top of the table. The different fields of the form are used to specify the parameters for the filter process. Once you have specified a filter, all the queries and related statistics shown within the Query Analyzer table are displayed in relation to the filter settings. For example, by default, the filter settings show the queries for the last 30 minutes. All the statistics shown are relative to the last 30 minutes, including average, maximum and execution counts.

The filtering functionality is available in a simple format, supporting simple statement and timing based filtering, and an advanced option allowing you to filter by specific columns within the Query Analyzer table.

The basic filter options are:

  • Statement Text and Value support text searching of the normalized query. For the search type you can specify either a basic text match (Contains), or a regular expression match (Regex). In addition to the basic text match, you can also search for a query that does not contain a particular string. For regular expression searches, you can specify whether the regular expression should match, or not match (negative regexp) the queries. Regular expressions are parsed using the standard MySQL REGEXP() function. For more information, see Regular Expressions.

    Note

    The search is performed against the canonical version of the query. You cannot search against specific text or values within the parameters of the query itself.

  • Statement Type: Limits the search to statements of a particular type (SELECT, LITERAL, etc.).

  • DB Name: Limits the queries to those executed within a specific database. The database match is performed using the LIKE match from the MySQL database, hence you can use the % and _ characters to multiple and single character matches. For more information, see Pattern Matching.

  • The Time Range menu selects whether the time selection for filtering should be based on the time interval (only queries recorded within the displayed time period are shown, using the Hours and Minutes pop-up), or whether the selection should be based on a time period (From/To), where you can select the time range to be displayed.

    Using the Interval mode shows queries within the given time period from the point the graph was updated. For example, if you select 30 minutes, then the queries shown were captured within the last 30 minutes. If you updated the display at 14:00, then the queries displayed would have been captured between 13:30 and 14:00. Using interval mode limits the timespan for the filter selection to a maximum of 23 hours and 59 minutes.

    Using the From/To time range lets you show queries between specific dates and times. Using this mode you can show only the queries received during a specific time span, and you can display the query history for a much longer time period, for as long as you have been recording query analysis information.

  • Limit specifies the number of queries to be displayed within each page.

To use the advanced filtering techniques, click show advanced. This provides additional filters:

  • Notices: Filters on the notices column, allowing you to filter the list to show only the queries that did not raise a notice, indicated a full table scan, or indicated that a bad index was used.

  • Two column filters are provided, which allow you to filter the queries based on specific values within any of the columns shown in the Query Analyzer report list.

    To use the column filters, you must specify the Column that you want to filter on, the Operator to use when performing the comparison and the Value that you want to compare.

    For example, to filter by showing all the queries that return more than 100 rows on average, set the Column to Average Rows, the Operator to >=, and the Value to 100.

  • The View selection determines whether the information should be returned on a group basis, where an aggregate of the same query executed on all monitored servers is shown, or on a Server basis, where queries are summarized by individual server. If the latter option has been selected, the table includes an additional column showing the server.

All the filter settings that you specify are used collectively, that is, all the specified filter options are used to match against the list of queries.

When you have set your filter parameters, you can update the Query Analysis display by clicking the filter button. To reset the fields to the default settings click the reset button.

If you want to make the current filter options the default when viewing the Query Analyzer page, click the Save As Default button. The settings are saved for the current user only.

27.3.4 Query Analyzer Settings

There are a number of settings related to the Query Analyzer data. To configure the Query Analyzer, go to the Configuration, Advisors page and select the Query Analysis Advisor category. Then choose Edit Advisor Configuration from the context menu of the Query Analysis Reporting Advisor.

Like with any Advisor, this may be set globally, or for a group or particular MySQL server.

Thee configuration options are:

  • Enable Example Query displays more information about individual queries. When enabled, queries and their data items (rather than the canonical form shown by default) are provided. Enabling this option could expose the full query statements and therefore could present a security issue.

    With the Example Query option enabled, an additional tab is available within the query summary details. For more information, see Section 27.3.1, “Getting Detailed Query Information”.

    If you enable Example Query, you can also enable Example Explain. To enable this tab, select the Enable Example Explain checkbox.

  • Enable Example Explain provides another tab when viewing a query where you can view the output from EXPLAIN output from MySQL for the selected query. This shows the full query and how the query was executed within the servers.

    Enabling this option might add overhead to the execution of your server, as the server runs an EXPLAIN statement each time it identifies a long running query.

  • Auto-Explain Threshold: EXPLAINs are generated for queries with a runtime above this threshold. (Format: hh:mm:ss.msec)

  • QRTi Threshold: Optimal time for response time index. For more information about QRTi, see Section 27.2, “Query Response Time index (QRTi)”.

You can also define a schedule for the advisor's data collection. For more information, see Section 19.4, “Advisor Schedules”

Important

If this advisor is disabled, Query Analysis data is no longer collected from the monitored instances. The Query Analyzer continues displaying data collected prior to the advisor being disabled.

If disabled, a message is displayed on the Query Analyzer page: "N of the selected servers do not have query analyzer enabled." where N is the number of servers.

27.3.5 Exporting Query Information

To get the text and details of the queries displayed on the Query Analyzer page, click one of the icons to the right of the Browse Queries label in the separator bar. The query information is exported as comma-separated data in a .csv file, with fields corresponding to the columns shown in the Monitor UI, and the time of the export encoded in the filename in UTC format. The icon representing a single page exports the query information for the currently displayed page only. The icon representing a stack of pages exports the query information for all available pages of query information.

Within the Query Analyzer pop-up, you can also export information about each data group as a .csv text file or a .png image file, using icons next to the labels on the left side. The output file is named according to the pattern Statement_Report_Summary_%server/group%_%creationtimestamp%.csv. The data exported by these icons includes:

  • Execution Time: Count

  • Executions: Exec Time, Max Exec Time, Min Exec Time, Average Exec Time

  • Rows: Rows, Max Rows, Min Rows, Average Rows

  • Kilobytes: Bytes, Max Bytes, Average Bytes

Note

Microsoft Excel users on Windows users can import the .csv file as a spreadsheet. If the file contains English text, typically you can double-click it to open in Excel. If the file contains localized Japanese text, you must use the File > Open menu choice within Excel to open the file.

In the Safari browser, exported files containing localized data might contain %NN character sequences in their names, due to browser issues with UTF-8 and Base64 encodings.