Were those queries intended to produce the same results? NB: I didn't add
the indexes you suggest.

mysql> SELECT COUNT(*) FROM dbmail_messages WHERE mailbox_idnr='5' AND
    -> (status='0' OR status='1') UNION
    -> SELECT COUNT(*) FROM dbmail_messages WHERE mailbox_idnr='5' AND
    -> (status='0' OR status='1') AND seen_flag=1 UNION
    -> SELECT COUNT(*) FROM dbmail_messages WHERE mailbox_idnr='5' AND
    -> (status='0' OR status='1') AND recent_flag=1;
+----------+
| COUNT(*) |
+----------+
|     1871 |
|     1666 |
+----------+
2 rows in set (0.27 sec)

mysql> SELECT COUNT(message_idnr), COUNT(message_idnr) - SUM(seen_flag),
    -> SUM(recent_flag) FROM dbmail_messages WHERE mailbox_idnr = '5'
    -> AND status < '2'\G

*************************** 1. row ***************************
                 COUNT(message_idnr): 1871
COUNT(message_idnr) - SUM(seen_flag): 205
                    SUM(recent_flag): 1871
1 row in set (0.09 sec)



On Wed, Mar 9, 2005, Geo Carncross <[EMAIL PROTECTED]>
said:

> On Wed, 2005-03-09 at 11:51 +0100, Thomas Mueller wrote:
>> Hi,
>> 
>> I get more and more user complaints that my IMAP server is terrible
>> slow, opening a mailbox takes very long.
>> 
>> I've analyzed that using PQA (http://pgfoundry.org/projects/pqa/, great
>> tool!), the output is attached if anyone is interested (includes all
>> databases, not only dbmail).
>> 
>> The main problem is in db.c, db_getmailbox():
>> SELECT COUNT(message_idnr), COUNT(message_idnr) - SUM(seen_flag),
>> SUM(recent_flag) FROM dbmail_messages WHERE mailbox_idnr = '5' AND
>> status < '2'
>> That query takes up to 15 seconds (!!).
> 
> A better query would be:
> 
> SELECT COUNT(*) FROM dbmail_messages WHERE mailbox_idnr='5' AND
> (status='0' OR status='1') UNION
> SELECT COUNT(*) FROM dbmail_messages WHERE mailbox_idnr='5' AND
> (status='0' OR status='1') AND seen_flag=1 UNION
> SELECT COUNT(*) FROM dbmail_messages WHERE mailbox_idnr='5' AND
> (status='0' OR status='1') AND recent_flag=1;
> 
> Then having the following indexes:
>       mailbox_idnr
>       mailbox_idnr,status
>       mailbox_idnr,status,seen_flag
>       mailbox_idnr,status,recent_flag
> 
> Then having an index on mailbox_idnr AND status will mean we never have
> to look at the database contents to answer the query (only examining the
> index.
> 
> If you feel REALLY wary about using UNION- make union-ability a flag and
> do each query separately if the backend says it can't do UNION.
> 
> We should also include the following indexes:
>       mailbox_idnr,message_idnr,status
>       mailbox_idnr,message_idnr
> 
> with SQLite, this plan never touches the records (only the index) - even
> though the plain is much longer (139 ops instead of 57) it's SO MUCH
> faster.
> 
> It would take [me] some time to actually test this with PgSQL - and I'll
> do that if someone who has an active dbmail+pg complains.
> 
> 
> BTW: I added this to my sql/sqlite/create_tables.sqlite for this.
> 
> CREATE INDEX dbmail_messages_7 ON dbmail_messages
> (mailbox_idnr,status,seen_flag);
> CREATE INDEX dbmail_messages_8 ON dbmail_messages
> (mailbox_idnr,status,recent_flag);


..

Reply via email to