Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Is my understanding of "select distinct" correct?

We recently discovered a performance problem with one of our systems and I think I have the fix but I'm not certain my understanding is correct.

In simplest form, we have a table blah into which we accumulate various values based on a key field. The basic form is:

recdate   date
rectime   time
system    varchar(20)
count     integer
accum1    integer
accum2    integer

There are a lot more accumulators than that but they're all of the same form. The primary key is made up of recdate, rectime and system.

As values are collected to the table, the count for a given recdate/rectime/system is incremented and the values for that key are added to the accumulators. That means the averages can be obtained by using accumN / count.

Now we also have a view over that table specified as follows:

create view blah_v (
    recdate, rectime, system, count,
    accum1,
    accum2
) as select distinct
    recdate, rectime, system, count,
    value (case when count > 0 then accum1 / count end, 0),
    value (case when count > 0 then accum2 / count end, 0)
    from blah;

In other words, the view gives us the average value of the accumulators rather than the sums. It also makes sure we don't get a divide-by-zero in those cases where the count is zero (these records do exist and we are not allowed to remove them so don't bother telling me they're rubbish - you're preaching to the choir).

We've noticed that the time difference between doing:

select distinct recdate from XX

varies greatly depending on whether we use the table or the view. I'm talking about the difference being 1 second for the table and 27 seconds for the view (with 100K rows).

We actually tracked it back to the select distinct. What seems to be happening is that the DBMS is actually loading all the rows in and sorting them so as to remove duplicates. That's fair enough, it's what we stupidly told it to do.

But I'm pretty sure the fact that the view includes every component of the primary key means that it's impossible to have duplicates anyway. We've validated the problem since, if we create another view without the distinct, it performs at the same speed as the underlying table.

I just wanted to confirm my understanding that a select distinct can not have duplicates if it includes all the primary key components. If that's so, then we can simply change the view appropriately.

like image 455
paxdiablo Avatar asked May 03 '10 07:05

paxdiablo


People also ask

What does SELECT distinct mean?

The SELECT DISTINCT statement is used to return only distinct (different) values. Inside a table, a column often contains many duplicate values; and sometimes you only want to list the different (distinct) values.

Why you shouldn't use SELECT distinct?

As a general rule, SELECT DISTINCT incurs a fair amount of overhead for the query. Hence, you should avoid it or use it sparingly. The idea of generating duplicate rows using JOIN just to remove them with SELECT DISTINCT is rather reminiscent of Sisyphus pushing a rock up a hill, only to have it roll back down again.

How do you use distinct?

The DISTINCT clause is used in the SELECT statement to filter out duplicate rows in the result set. You can use DISTINCT when you select a single column, or when you select multiple columns as we did in our example.

What is the difference between SELECT and SELECT distinct?

SELECT * will select all the columns from the tables in the FROM clause; SELECT DISTINCT * will find all unique combinations of row data for tables in the FROM clause. DISTINCT forces a sort and unique filtering operations making it far slower for large data.

Can I use SELECT * with distinct?

We can use select with a distinct statement to retrieve unique records from the table. Name of column1 to the name of column N – This is the table column that was used with distinct keywords to retrieve data from a table.


2 Answers

In this case the DISTINCT isn't doing you any good because your distinct fields are already guaranteed to be unique because of the PRIMARY KEY constraint on the underlying table. You might try rewriting the view as:

create view blah_v ( 
    recdate, rectime, system, count, 
    accum1, 
    accum2 
) as select
       recdate, rectime, system, count, 
       case when count > 0 then accum1 / count else 0 end,
       case when count > 0 then accum2 / count else 0 end,
       from blah;

Share and enjoy.

like image 166

Yes, there's no point in asking for distinct results when all the primary key elements are included.

The table's primary key constraint already precludes duplicates across those columns, but your DBMS will still process the tuples to ensure they are distinct.

like image 38
John Flatness Avatar answered Sep 23 '22 13:09

John Flatness