Run MySQL federated queries
As a data analyst, you can query relational data residing in MySQL directly from BigQuery in real time, without copying or moving data.
BigQuery MySQL federation uses the
BigQuery Connection API to connect to MySQL database engines. You
can then use the
EXTERNAL_QUERY function
to send your SQL query directly to MySQL for execution, and the
results are streamed directly back.
Limitations
MySQL federated queries are subject to the following limitations:
- You can only execute read-only queries through the
EXTERNAL_QUERYfunction. Data definition language (DDL) and data manipulation language (DML) statements aren't supported. - Federation is only accessible through the
EXTERNAL_QUERYfunction. Creating BigQuery external tables or permanent datasets that directly map to MySQL tables isn't supported. - Federated query latency might be noticeably higher than executing the query directly in MySQL.
- The underlying connection service might hibernate inactive connections. The first query that uses a MySQL connection after a period of inactivity might take more than a minute to run while the connector initializes.
- DNS peering isn't supported. You must connect using an IP address or a fully resolvable hostname within your VPC network.
- The MySQL SQL query must specify explicit column aliases for any
columns that contain function results or expressions (for example,
SELECT COUNT(*) AS total_count). Unaliased expressions produce column names with special characters that are invalid in BigQuery table schema definitions. - When the usage of the Compute Engine API in the query project is restricted by VPC Service Controls, the federated query fails if the connection uses a network attachment. Ensure that appropriate VPC Service Controls ingress and egress rules are configured.
No additional SQL pushdowns are supported for MySQL. Filters and aggregations in the outer BigQuery query aren't pushed down into the inner query within the
EXTERNAL_QUERYfunction. You must specify predicates and column projections directly inside the inner MySQL SQL statement to limit the rows and columns that are transferred across the network.Only MySQL database username and password authentication is supported. Third-party identity providers, Kerberos, and cloud provider IAM authentication aren't supported.
CREATE TABLE ... AS SELECT(CTAS) statements fail withUnsupported type INT32orUnsupported type FLOATerrors if the query selects 32-bit integer columns (TINYINT,SMALLINT, andBOOLEAN/TINYINT(1)) or single-precision float columns (FLOAT). To save query results into a new BigQuery table, explicitly cast integer columns toINT64and float columns toFLOAT64in your query:CREATE TABLE mydataset.mytable AS SELECT CAST(tiny_col AS INT64) AS tiny_col, CAST(small_col AS INT64) AS small_col, ... FROM EXTERNAL_QUERY(...);
Inserting into an existing table with
INSERT INTO <table> SELECT ...succeeds without manual casts because BigQuery automatically widensINT32andFLOATvalues to match the target table'sINT64andFLOAT64columns.While MySQL
DECIMALandNUMERICcolumns map toBIGNUMERIC(76, 38), MySQL allows precision up to 65. If a value contains more than 38 integer digits (precision minus scale is greater than 38), it exceeds theBIGNUMERICinteger range and the query fails at runtime. To query values with more than 38 integer digits, cast them toCHARorVARCHARin theEXTERNAL_QUERYstatement.The
TIMEdata type truncates fractional sub-second (microsecond) values to whole seconds (for example,12:34:56.789123becomes12:34:56). Furthermore, MySQLTIMEsupports elapsed durations from-838:59:59to838:59:59, whereas BigQueryTIMEonly supports time-of-day values from00:00:00to23:59:59.999999. Values outside00:00:00to23:59:59cause runtime query errors. If microsecond precision or elapsed duration values are required, cast the column toCHARorVARCHARinside theEXTERNAL_QUERYstatement.Dates and timestamps prior to October 15, 1582 are subject to a 10-day calendar shift due to the historical Gregorian calendar transition. To preserve exact historical dates prior to 1582, cast them to
CHARorVARCHARin theEXTERNAL_QUERYstatement.
Supported MySQL environments and versions
Query federation supports MySQL databases across the following deployment environments:
- Cloud-hosted or on-premises MySQL databases accessible through public IP addresses or network attachments (over Cloud VPN or Cloud Interconnect)
- Self-hosted MySQL instances on Compute Engine or other infrastructure
- MySQL 8.4 LTS and 8.0
Before you begin
Ensure that your BigQuery administrator has created a MySQL connection and shared it with you.
Required roles
To get the permissions that
you need to query MySQL,
ask your administrator to grant you the
BigQuery Connection User (roles/bigquery.connectionUser) IAM role on the project.
For more information about granting roles, see Manage access to projects, folders, and organizations.
You might also be able to get the required permissions through custom roles or other predefined roles.
Query data
To send a federated query to MySQL from a GoogleSQL
query, use the EXTERNAL_QUERY function.
The following example is a federated query that joins customer records in
BigQuery named mydataset.customers with transactional sales
orders in MySQL:
SELECT c.customer_id, c.name, fo.first_order_date FROM mydataset.customers AS c LEFT OUTER JOIN EXTERNAL_QUERY( 'projects/my-project/locations/us-central1/connections/mysql_prod_conn', '''SELECT CUSTOMER_ID, MIN(ORDER_DATE) AS first_order_date FROM ORDERS GROUP BY CUSTOMER_ID''') AS fo ON fo.customer_id = c.customer_id GROUP BY c.customer_id, c.name, fo.first_order_date;
View a MySQL table schema
You can query the MySQL INFORMATION_SCHEMA views through
EXTERNAL_QUERY to inspect database metadata, discover tables, and review
column schemas before running analytics.
List all databases
SELECT * FROM EXTERNAL_QUERY( 'projects/PROJECT_ID/locations/LOCATION/connections/CONNECTION_ID', '''SELECT SCHEMA_NAME, DEFAULT_CHARACTER_SET_NAME FROM INFORMATION_SCHEMA.SCHEMATA''');
List tables in a database
SELECT * FROM EXTERNAL_QUERY( 'projects/PROJECT_ID/locations/LOCATION/connections/CONNECTION_ID', """SELECT TABLE_SCHEMA, TABLE_NAME, TABLE_TYPE, ENGINE FROM INFORMATION_SCHEMA.TABLES WHERE TABLE_SCHEMA = 'DATABASE_NAME'""");
View columns and data types in a table
SELECT * FROM EXTERNAL_QUERY( 'projects/PROJECT_ID/locations/LOCATION/connections/CONNECTION_ID', """SELECT COLUMN_NAME, DATA_TYPE, IS_NULLABLE, COLUMN_TYPE FROM INFORMATION_SCHEMA.COLUMNS WHERE TABLE_SCHEMA = 'DATABASE_NAME' AND TABLE_NAME = 'TABLE_NAME'""");
Data type mapping
When you execute a federated query, BigQuery converts the data from MySQL into GoogleSQL data types according to the following table:
| MySQL data type | BigQuery data type |
|---|---|
| Numeric types | |
BOOLEAN, BOOL, TINYINT(1) |
INT64 (interactive queries; see Limitations for CREATE TABLE ... AS SELECT) |
TINYINT, SMALLINT |
INT64 (interactive queries; see Limitations for CREATE TABLE ... AS SELECT) |
MEDIUMINT, INT, INTEGER |
INT64 |
BIGINT |
INT64 |
BIGINT UNSIGNED, BIGINT ZEROFILL, SERIAL |
BIGNUMERIC(76, 38) |
DECIMAL, DEC, NUMERIC, FIXED |
BIGNUMERIC(76, 38) |
FLOAT |
FLOAT64 (interactive queries; see Limitations for CREATE TABLE ... AS SELECT) |
DOUBLE, DOUBLE PRECISION, REAL |
FLOAT64 |
| Date and time types | |
DATE |
DATE |
DATETIME |
DATETIME |
TIMESTAMP |
TIMESTAMP |
TIME |
TIME |
| String and text types | |
CHAR |
STRING |
VARCHAR |
STRING |
BINARY |
BYTES |
VARBINARY |
BYTES |
TINYBLOB, BLOB, MEDIUMBLOB, LONGBLOB |
BYTES |
TINYTEXT, TEXT, MEDIUMTEXT, LONGTEXT |
STRING |
ENUM |
STRING |
SET |
STRING |
Pricing
The cost of running a federated query is based on three factors:
- The compute cost of executing the query in MySQL (charged by your MySQL database provider or hosting environment)
- The bandwidth cost of transferring the query results from MySQL to BigQuery (egress network charges from your database hosting provider)
- The compute cost of executing the query in BigQuery
Any MySQL compute and egress costs are billed directly by your
MySQL provider or infrastructure host, not Google. To limit
bandwidth cost, we recommend that you write the query in the EXTERNAL_QUERY
statement so that it excludes all columns and rows that aren't needed to compute
the final result.
There is no additional cost for running federated queries in BigQuery. For more information about BigQuery pricing, see Pricing.
If your connection uses Google Cloud networking components, the following pricing might also apply:
What's next
- Learn how to connect to MySQL.
- Learn more about federated queries.
- Learn about managing connections.