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);
..