Optimal GROUP BY Clauses

   

Optimal GROUP BY Clauses

We've already mentioned that GROUP BY performs better if you keep the number of grouping columns small. One way you can do so is to avoid grouping redundant columns , as in this example:

 SELECT secondary_key_column, primary_key_column, COUNT(*)   FROM Table1   GROUP BY secondary_key_column, primary_key_column 

Because primary key columns are unique and may not contain NULL by definition, the mention of secondary_key_column in this example is redundant. The problem is that if you take secondary_key_column out of the GROUP BY clause, you'll get an error message. All DBMSs except MySQL and Sybase will tell you that you can't have secondary_key_column in the select list if it's not also in the GROUP BY list. This is how to write a query that's legal and that's faster:

 SELECT MIN(secondary_key_column), primary_key_column, COUNT(*)   FROM Table1   GROUP BY primary_key_column GAIN: 4/7 

WARNING

Don't do this for Ingres; it shows a loss. The gain shown is for only seven DBMSs.


Here are two ways to speed up GROUP BY when you're joining tables.

Reduce before you expand

GROUP BY tends to reduce row counts, and JOIN tends to expand row counts. Because a DBMS must evaluate FROM and WHERE clauses before GROUP BY clauses, this tip is not easy to put into practice, but there is a way. You can make a join happen late by replacing it with a set operator . (The SQL Standard set operators are UNION, EXCEPT, and INTERSECT.) For example, replace Statement #1 with Statement #2:

 Statement #1: SELECT SUM(Table1.column2), SUM(Table2.column2)   FROM Table1 INNER JOIN Table2        ON Table1.column1 = Table2.column1   GROUP BY Table1.column1 Statement #2: SELECT column1, SUM(column2), 0   FROM Table1   GROUP BY column1 INTERSECT SELECT column1, 0, SUM(column2)   FROM Table2   GROUP BY column1 GAIN: 2/2 

Portability

Informix, Ingres, InterBase, Microsoft, MySQL, and Sybase don't support INTERSECT. The gain shown is for only two DBMSs.


GROUP on the same table

When you're grouping joined tables, the GROUP BY column should be from the same table as the column(s) on which you're applying a set function. We're passing this advice along because some vendors think it's important enough to mention in their documentation.

Also to do with joins and GROUP BY, you can improve performance by avoiding joins altogether. Consider this SELECT:

 SELECT COUNT(*) FROM Table1, Table2    WHERE Table1.column1 = Table2.column1 

If Table1.column1 is unique, you could replace the join with a subquery. Transform the SELECT to:

 SELECT COUNT(*) FROM Table2   WHERE Table2.column1 IN     (SELECT Table1.column1 FROM Table1) GAIN: 4/6 

WARNING

Don't do this for Oracle; it shows a loss. The gain shown is for only six DBMSs (see Portability note).


Portability

MySQL doesn't support subqueries. The gain shown is for only six DBMSs.


HAVING

Most DBMSs do not merge WHERE and HAVING clauses. This means the following statements are logically the same but won't run at the same speed:

 Query with WHERE and HAVING: SELECT column1 FROM Table1   WHERE column2 = 5   GROUP BY column1     HAVING column1 > 6 Query with WHERE only: SELECT column1 FROM Table1   WHERE column2 = 5     AND column1 > 6   GROUP BY column1 GAIN: 3/8 

The "Query with WHERE only" runs faster on three of the Big Eight. You should use this type of query except in the rare cases where you need to defer the filtering implied by column1 > 6 for example, if the comparison is hard to evaluate.

Alternatives to GROUP BY

If you're writing a query that doesn't involve set functions, you can use DISTINCT as an alternative to GROUP BY. DISTINCT has three advantages: It's simpler, it's legal to use in expressions, andwith some DBMSsit's faster. So instead of using Query #1, use the alternative Query #2:

 Query #1: SELECT column1    FROM Table1    GROUP BY column1 Query #2: SELECT DISTINCT column1    FROM Table1 GAIN: 4/8 

The Bottom Line: Optimal GROUP BY Clauses

GROUP BY performs better if you keep the number of grouping columns small.

Avoid grouping redundant columns by using set functions.

When you're grouping joined tables, reduce before you expand. You can make a join happen late by replacing it with a set operator.

When you're grouping joined tables, the GROUP BY column should be from the same table as the column(s) on which you're applying a set function.

You can improve performance on some grouped joins by replacing the join with a subquery.

Most DBMSs do not merge WHERE and HAVING clauses. Write your queries with only a WHERE clause wherever possible.

Use DISTINCT instead of GROUP BY if your query doesn't involve set functions.

   


SQL Performance Tuning
SQL Performance Tuning
ISBN: 0201791692
EAN: 2147483647
Year: 2005
Pages: 125

flylib.com © 2008-2017.
If you may any questions please contact us: flylib@qtcs.net