Porting SQL from Other Database Systems to Impala
Although Impala uses standard SQL for queries, you might need to modify SQL source when bringing applications to Impala, due to variations in data types, built-in functions, vendor language extensions, and Hadoop-specific syntax. Even when SQL is working correctly, you might make further minor modifications for best performance.
Porting DDL and DML Statements
When adapting SQL code from a traditional database system to Impala, expect to find a number of differences in the DDL statements that you use to set up the schema. Clauses related to physical layout of files, tablespaces, and indexes have no equivalent in Impala. You might restructure your schema considerably to account for the Impala partitioning scheme and Hadoop file formats.
Expect SQL queries to have a much higher degree of compatibility. With modest rewriting to address vendor extensions and features not yet supported in Impala, you might be able to run identical or almost-identical query text on both systems.
Therefore, consider separating out the DDL into a separate Impala-specific setup script. Focus your reuse and ongoing tuning efforts on the code for SQL queries.
Porting Data Types from Other Database Systems
-
Change any
VARCHAR
,VARCHAR2
, andCHAR
columns toSTRING
. Remove any length constraints from the column declarations; for example, changeVARCHAR(32)
orCHAR(1)
toSTRING
. Impala is very flexible about the length of string values; it does not impose any length constraints or do any special processing (such as blank-padding) forSTRING
columns. (In Impala 2.0 and higher, there are data typesVARCHAR
andCHAR
, with length constraints for both types and blank-padding forCHAR
. However, for performance reasons, it is still preferable to useSTRING
columns where practical.) -
For national language character types such as
NCHAR
,NVARCHAR
, orNCLOB
, be aware that while Impala can store and query UTF-8 character data, currently some string manipulation operations only work correctly with ASCII data. See STRING Data Type for details. -
Change any
DATE
,DATETIME
, orTIME
columns toTIMESTAMP
. Remove any precision constraints. Remove any timezone clauses, and make sure your application logic or ETL process accounts for the fact that Impala expects allTIMESTAMP
values to be in Coordinated Universal Time (UTC). See TIMESTAMP Data Type for information about theTIMESTAMP
data type, and Impala Date and Time Functions for conversion functions for different date and time formats.You might also need to adapt date- and time-related literal values and format strings to use the supported Impala date and time formats. If you have date and time literals with different separators or different numbers of
YY
,MM
, and so on placeholders than Impala expects, consider using calls toregexp_replace()
to transform those values to the Impala-compatible format. See TIMESTAMP Data Type for information about the allowed formats for date and time literals, and Impala String Functions for string conversion functions such asregexp_replace()
.Instead of
SYSDATE
, call the functionNOW()
.Instead of adding or subtracting directly from a date value to produce a value N days in the past or future, use an
INTERVAL
expression, for exampleNOW() + INTERVAL 30 DAYS
. -
Although Impala supports
INTERVAL
expressions for datetime arithmetic, as shown in TIMESTAMP Data Type,INTERVAL
is not available as a column data type in Impala. For anyINTERVAL
values stored in tables, convert them to numeric values that you can add or subtract using the functions in Impala Date and Time Functions. For example, if you had a tableDEADLINES
with anINT
columnTIME_PERIOD
, you could construct dates N days in the future like so:SELECT NOW() + INTERVAL time_period DAYS from deadlines;
-
For
YEAR
columns, change to the smallest Impala integer type that has sufficient range. See Data Types for details about ranges, casting, and so on for the various numeric data types. -
Change any
DECIMAL
andNUMBER
types. If fixed-point precision is not required, you can useFLOAT
orDOUBLE
on the Impala side depending on the range of values. For applications that require precise decimal values, such as financial data, you might need to make more extensive changes to table structure and application logic, such as using separate integer columns for dollars and cents, or encoding numbers as string values and writing UDFs to manipulate them. See Data Types for details about ranges, casting, and so on for the various numeric data types. -
FLOAT
,DOUBLE
, andREAL
types are supported in Impala. Remove any precision and scale specifications. (In Impala,REAL
is just an alias forDOUBLE
; columns declared asREAL
are turned intoDOUBLE
behind the scenes.) See Data Types for details about ranges, casting, and so on for the various numeric data types. -
Most integer types from other systems have equivalents in Impala, perhaps under different names such as
BIGINT
instead ofINT8
. For any that are unavailable, for exampleMEDIUMINT
, switch to the smallest Impala integer type that has sufficient range. Remove any precision specifications. See Data Types for details about ranges, casting, and so on for the various numeric data types. -
Remove any
UNSIGNED
constraints. All Impala numeric types are signed. See Data Types for details about ranges, casting, and so on for the various numeric data types. -
For any types holding bitwise values, use an integer type with enough range to hold all the relevant bits within a positive integer. See Data Types for details about ranges, casting, and so on for the various numeric data types.
For example,
TINYINT
has a maximum positive value of 127, not 256, so to manipulate 8-bit bitfields as positive numbers switch to the next largest typeSMALLINT
.[localhost:21000] > select cast(127*2 as tinyint); +--------------------------+ | cast(127 * 2 as tinyint) | +--------------------------+ | -2 | +--------------------------+ [localhost:21000] > select cast(128 as tinyint); +----------------------+ | cast(128 as tinyint) | +----------------------+ | -128 | +----------------------+ [localhost:21000] > select cast(127*2 as smallint); +---------------------------+ | cast(127 * 2 as smallint) | +---------------------------+ | 254 | +---------------------------+
Impala does not support notation such as
b'0101'
for bit literals. -
For BLOB values, use
STRING
to representCLOB
orTEXT
types (character based large objects) up to 32 KB in size. Binary large objects such asBLOB
,RAW
BINARY
, andVARBINARY
do not currently have an equivalent in Impala. -
For Boolean-like types such as
BOOL
, use the ImpalaBOOLEAN
type. -
Because Impala currently does not support composite or nested types, any spatial data types in other database systems do not have direct equivalents in Impala. You could represent spatial values in string format and write UDFs to process them. See Impala User-Defined Functions (UDFs) for details. Where practical, separate spatial types into separate tables so that Impala can still work with the non-spatial data.
-
Take out any
DEFAULT
clauses. Impala can use data files produced from many different sources, such as Pig, Hive, or MapReduce jobs. The fast import mechanisms ofLOAD DATA
and external tables mean that Impala is flexible about the format of data files, and Impala does not necessarily validate or cleanse data before querying it. When copying data through ImpalaINSERT
statements, you can use conditional functions such asCASE
orNVL
to substitute some other value forNULL
fields; see Impala Conditional Functions for details. -
Take out any constraints from your
CREATE TABLE
andALTER TABLE
statements, for examplePRIMARY KEY
,FOREIGN KEY
,UNIQUE
,NOT NULL
,UNSIGNED
, orCHECK
constraints. Impala can use data files produced from many different sources, such as Pig, Hive, or MapReduce jobs. Therefore, Impala expects initial data validation to happen earlier during the ETL or ELT cycle. After data is loaded into Impala tables, you can perform queries to test forNULL
values. When copying data through ImpalaINSERT
statements, you can use conditional functions such asCASE
orNVL
to substitute some other value forNULL
fields; see Impala Conditional Functions for details.Do as much verification as practical before loading data into Impala. After data is loaded into Impala, you can do further verification using SQL queries to check if values have expected ranges, if values are
NULL
or not, and so on. If there is a problem with the data, you will need to re-run earlier stages of the ETL process, or do anINSERT ... SELECT
statement in Impala to copy the faulty data to a new table and transform or filter out the bad values. -
Take out any
CREATE INDEX
,DROP INDEX
, andALTER INDEX
statements, and equivalentALTER TABLE
statements. Remove anyINDEX
,KEY
, orPRIMARY KEY
clauses fromCREATE TABLE
andALTER TABLE
statements. Impala is optimized for bulk read operations for data warehouse-style queries, and therefore does not support indexes for its tables. -
Calls to built-in functions with out-of-range or otherwise incorrect arguments, return
NULL
in Impala as opposed to raising exceptions. (This rule applies even when theABORT_ON_ERROR=true
query option is in effect.) Run small-scale queries using representative data to doublecheck that calls to built-in functions are returning expected values rather thanNULL
. For example, unsupportedCAST
operations do not raise an error in Impala:select cast('foo' as int); +--------------------+ | cast('foo' as int) | +--------------------+ | NULL | +--------------------+
-
For any other type not supported in Impala, you could represent their values in string format and write UDFs to process them. See Impala User-Defined Functions (UDFs) for details.
-
To detect the presence of unsupported or unconvertable data types in data files, do initial testing with the
ABORT_ON_ERROR=true
query option in effect. This option causes queries to fail immediately if they encounter disallowed type conversions. See ABORT_ON_ERROR Query Option for details. For example:set abort_on_error=true; select count(*) from (select * from t1); -- The above query will fail if the data files for T1 contain any -- values that can't be converted to the expected Impala data types. -- For example, if T1.C1 is defined as INT but the column contains -- floating-point values like 1.1, the query will return an error.
SQL Statements to Remove or Adapt
Some SQL statements or clauses that you might be familiar with are not currently supported in Impala:
-
Impala has no
DELETE
statement. Impala is intended for data warehouse-style operations where you do bulk moves and transforms of large quantities of data. Instead of usingDELETE
, useINSERT OVERWRITE
to entirely replace the contents of a table or partition, or useINSERT ... SELECT
to copy a subset of data (everything but the rows you intended to delete) from one table to another. See DML Statements for an overview of Impala DML statements. -
Impala has no
UPDATE
statement. Impala is intended for data warehouse-style operations where you do bulk moves and transforms of large quantities of data. Instead of usingUPDATE
, do all necessary transformations early in the ETL process, such as in the job that generates the original data, or when copying from one table to another to convert to a particular file format or partitioning scheme. See DML Statements for an overview of Impala DML statements. -
Impala has no transactional statements, such as
COMMIT
orROLLBACK
. Impala effectively works like theAUTOCOMMIT
mode in some database systems, where changes take effect as soon as they are made. -
If your database, table, column, or other names conflict with Impala reserved words, use different names or quote the names with backticks. See Impala Reserved Words for the current list of Impala reserved words.
Conversely, if you use a keyword that Impala does not recognize, it might be interpreted as a table or column alias. For example, in
SELECT * FROM t1 NATURAL JOIN t2
, Impala does not recognize theNATURAL
keyword and interprets it as an alias for the tablet1
. If you experience any unexpected behavior with queries, check the list of reserved words to make sure all keywords in join andWHERE
clauses are recognized. -
Impala supports subqueries only in the
FROM
clause of a query, not within theWHERE
clauses. Therefore, you cannot use clauses such asWHERE column IN (subquery)
. Also, Impala does not allowEXISTS
orNOT EXISTS
clauses (althoughEXISTS
is a reserved keyword). -
Impala supports
UNION
andUNION ALL
set operators, but notINTERSECT
. PreferUNION ALL
overUNION
when you know the data sets are disjoint or duplicate values are not a problem;UNION ALL
is more efficient because it avoids materializing and sorting the entire result set to eliminate duplicate values. -
Within queries, Impala requires query aliases for any subqueries:
-- Without the alias 'contents_of_t1' at the end, query gives syntax error. select count(*) from (select * from t1) contents_of_t1;
-
When an alias is declared for an expression in a query, that alias cannot be referenced again within the same query block:
-- Can't reference AVERAGE twice in the SELECT list where it's defined. select avg(x) as average, average+1 from t1 group by x; ERROR: AnalysisException: couldn't resolve column reference: 'average' -- Although it can be referenced again later in the same query. select avg(x) as average from t1 group by x having average > 3;
For Impala, either repeat the expression again, or abstract the expression into a
WITH
clause, creating named columns that can be referenced multiple times anywhere in the base query:-- The following 2 query forms are equivalent. select avg(x) as average, avg(x)+1 from t1 group by x; with avg_t as (select avg(x) average from t1 group by x) select average, average+1 from avg_t;
-
Impala does not support certain rarely used join types that are less appropriate for high-volume tables used for data warehousing. In some cases, Impala supports join types but requires explicit syntax to ensure you do not do inefficient joins of huge tables by accident. For example, Impala does not support natural joins or anti-joins, and requires the
CROSS JOIN
operator for Cartesian products. See Joins in Impala SELECT Statements for details on the syntax for Impala join clauses. -
Impala has a limited choice of partitioning types. Partitions are defined based on each distinct combination of values for one or more partition key columns. Impala does not redistribute or check data to create evenly distributed partitions; you must choose partition key columns based on your knowledge of the data volume and distribution. Adapt any tables that use range, list, hash, or key partitioning to use the Impala partition syntax for
CREATE TABLE
andALTER TABLE
statements. Impala partitioning is similar to range partitioning where every range has exactly one value, or key partitioning where the hash function produces a separate bucket for every combination of key values. See Partitioning for Impala Tables for usage details, and CREATE TABLE Statement and ALTER TABLE Statement for syntax.Note: Because the number of separate partitions is potentially higher than in other database systems, keep a close eye on the number of partitions and the volume of data in each one; scale back the number of partition key columns if you end up with too many partitions with a small volume of data in each one. Remember, to distribute work for a query across a cluster, you need at least one HDFS block per node. HDFS blocks are typically multiple megabytes, especially for Parquet files. Therefore, if each partition holds only a few megabytes of data, you are unlikely to see much parallelism in the query because such a small amount of data is typically processed by a single node. -
For "top-N" queries, Impala uses the
LIMIT
clause rather than comparing against a pseudocolumn namedROWNUM
orROW_NUM
. See LIMIT Clause for details.
SQL Constructs to Doublecheck
Some SQL constructs that are supported have behavior or defaults more oriented towards convenience than optimal performance. Also, sometimes machine-generated SQL, perhaps issued through JDBC or ODBC applications, might have inefficiencies or exceed internal Impala limits. As you port SQL code, be alert and change these things where appropriate:
-
A
CREATE TABLE
statement with noSTORED AS
clause creates data files in plain text format, which is convenient for data interchange but not a good choice for high-volume data with high-performance queries. See How Impala Works with Hadoop File Formats for why and how to use specific file formats for compact data and high-performance queries. Especially see Using the Parquet File Format with Impala Tables, for details about the file format most heavily optimized for large-scale data warehouse queries. -
A
CREATE TABLE
statement with noPARTITIONED BY
clause stores all the data files in the same physical location, which can lead to scalability problems when the data volume becomes large.On the other hand, adapting tables that were already partitioned in a different database system could produce an Impala table with a high number of partitions and not enough data in each one, leading to underutilization of Impala's parallel query features.
See Partitioning for Impala Tables for details about setting up partitioning and tuning the performance of queries on partitioned tables.
-
The
INSERT ... VALUES
syntax is suitable for setting up toy tables with a few rows for functional testing, but because each such statement creates a separate tiny file in HDFS, it is not a scalable technique for loading megabytes or gigabytes (let alone petabytes) of data. Consider revising your data load process to produce raw data files outside of Impala, then setting up Impala external tables or using theLOAD DATA
statement to use those data files instantly in Impala tables, with no conversion or indexing stage. See External Tables and LOAD DATA Statement for details about the Impala techniques for working with data files produced outside of Impala; see Data Loading and Querying Examples for examples of ETL workflow for Impala. -
If your ETL process is not optimized for Hadoop, you might end up with highly fragmented small data files, or a single giant data file that cannot take advantage of distributed parallel queries or partitioning. In this case, use an
INSERT ... SELECT
statement to copy the data into a new table and reorganize into a more efficient layout in the same operation. See INSERT Statement for details about theINSERT
statement.You can do
INSERT ... SELECT
into a table with a more efficient file format (see How Impala Works with Hadoop File Formats) or from an unpartitioned table into a partitioned one (see Partitioning for Impala Tables). -
The number of expressions allowed in an Impala query might be smaller than for some other database systems, causing failures for very complicated queries (typically produced by automated SQL generators). Where practical, keep the number of expressions in the
WHERE
clauses to approximately 2000 or fewer. As a workaround, set the query optionDISABLE_CODEGEN=true
if queries fail for this reason. See DISABLE_CODEGEN Query Option for details. -
If practical, rewrite
UNION
queries to use theUNION ALL
operator instead. PreferUNION ALL
overUNION
when you know the data sets are disjoint or duplicate values are not a problem;UNION ALL
is more efficient because it avoids materializing and sorting the entire result set to eliminate duplicate values.
Next Porting Steps after Verifying Syntax and Semantics
Throughout this section, some of the decisions you make during the porting process also have a substantial impact on performance. After your SQL code is ported and working correctly, doublecheck the performance-related aspects of your schema design, physical layout, and queries to make sure that the ported application is taking full advantage of Impala's parallelism, performance-related SQL features, and integration with Hadoop components.
-
Have you run the
COMPUTE STATS
statement on each table involved in join queries? Have you also runCOMPUTE STATS
for each table used as the source table in anINSERT ... SELECT
orCREATE TABLE AS SELECT
statement? - Are you using the most efficient file format for your data volumes, table structure, and query characteristics?
-
Are you using partitioning effectively? That is, have you partitioned on columns that are often used for
filtering in
WHERE
clauses? Have you partitioned at the right granularity so that there is enough data in each partition to parallelize the work for each query? - Does your ETL process produce a relatively small number of multi-megabyte data files (good) rather than a huge number of small files (bad)?
See Tuning Impala for Performance for details about the whole performance tuning process.