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);
> Obviously that doesn't scale at all - dbmail is not usable on PostgreSQL
> with lot of mails and/or users.
>
> If I replace COUNT(message_idnr) with the value I get the query is about
> 30 (!) times faster and takes about 0.4 seconds:
>
> SELECT 611, 611 - SUM(seen_flag), SUM(recent_flag) FROM dbmail_messages
> WHERE mailbox_idnr = '5' AND status < '2';
>
> So the solution is easy: add a row to dbmail_mailboxes that contains the
> number of messages. The row is updated by a trigger when messages are
> inserted or deleted. That is a quick and easy fix (only one query in the
> dbmail code has to be changed) - but that doesn't work for MySQL, I know :-/
I do not think this would work as well as you think this would work.
> I think in this case database abstraction simply doesn't work. We have
> to use two different queries in the code, but I might be wrong. Does
> anyone have a better solution?
>
>
> Thomas
> HTML page attachment (pg.html)
> SQL Query Analysis (generated Wed Mar 09 09:14:24 CET 2005)
>
>
> ______________________________________________________________________
> Reports
> Overall statistics
> Queries by type
> Queries that took up the most time
> Slowest queries
> Most frequent queries
>
> ______________________________________________________________________
> Overall statistics
> 375375 queries
> 262 unique queries
> Total query duration was 7389.75 seconds
> Longest query (SELECT pnd."SeqId",pnd."TableName",
> pnd."Op",pnddata."IsKey", pnddata."Data" AS "Data" FROM "Pending" pnd,
> "PendingData" pnddata WHERE pnd."SeqId" = pnddata."SeqId" AND
> pnd."XID"={ } ORDER BY "SeqId", "IsKey" DESC) ran in 84.216 seconds
> Shortest query (SET DATESTYLE = ISO) ran in 0.000 seconds
> Log file parsed in 358.1 seconds
> Queries by type
> Type
> Count
> Percentage
> SELECT
> 306035
> 82
> INSERT
> 46531
> 12
> UPDATE
> 10028
> 3
> DELETE
> 10415
> 3
> Queries that took up the most time
> Rank
> Total time
> (seconds)
> Times executed
> Query text
> 1
> 2532.248
> 9593
> SELECT COUNT
> (message_idnr),
> COUNT
> (message_idnr) -
> SUM(seen_flag),
> SUM(recent_flag)
> FROM
> dbmail_messages
> WHERE
> mailbox_idnr =
> { } AND status <
> { }
> 2
> 1398.038
> 9526
> SELECT
> message_idnr FROM
> dbmail_messages
> WHERE
> mailbox_idnr =
> { } AND status <
> { } ORDER BY
> message_idnr ASC
> 3
> 515.294
> 9933
> INSERT INTO
> "PendingData" ("SeqId","IsKey","Data") VALUES(currval({ }),{ },$1)
> 4
> 340.673
> 32
> SELECT
> filename,md5sum,size,mtime FROM filelist WHERE owner={ } AND filename LIKE {
> } EXCEPT SELECT filename,md5sum,size,mtime FROM filelist WHERE owner={ } AND
> filename LIKE { } ORDER BY filename ASC LIMIT { } OFFSET { }
> 5
> 312.432
> 3375
> select
> a.oid,a.relname,a.relnamespace,a.relpages,a.relisshared,a.reltuples,b.schemaname,b.n_tup_ins,b.n_tup_upd,b.n_tup_del
> from pg_class a, pg_stat_all_tables b where a.oid=b.relid and a.relkind = {
> } and schemaname not like { }
> 6
> 302.986
> 1815
> SELECT seen_flag,
> answered_flag,
> deleted_flag,
> flagged_flag,
> draft_flag,
> recent_flag,
> TO_CHAR
> (internal_date,
> { } ), rfcsize,
> message_idnr FROM
> dbmail_messages
> msg,
> dbmail_physmessage pm WHERE pm.id = msg.physmessage_id AND message_idnr
> BETWEEN { } AND { } AND mailbox_idnr = { } AND status < { } ORDER BY
> message_idnr ASC
> 7
> 209.489
> 8932
> INSERT INTO
> "MirroredTransaction" ("XID","LastSeqId","MirrorHostId") VALUES ({ },{ },{ })
> 8
> 202.152
> 41707
> SELECT messageblk
> FROM
> dbmail_messageblks blk, dbmail_messages msg WHERE blk.physmessage_id =
> msg.physmessage_id AND msg.message_idnr = { } ORDER BY blk.messageblk_idnr
> ASC LIMIT { }
> 9
> 198.843
> 8932
> DELETE FROM
> "Pending" WHERE
> "XID"={ } AND
> (SELECT COUNT(*)
> FROM
> "MirroredTransaction" WHERE "XID"={ })=(SELECT COUNT(*) FROM "MirrorHost")
> 10
> 196.429
> 8988
> SELECT
> pnd."SeqId",pnd."TableName", pnd."Op",pnddata."IsKey", pnddata."Data" AS
> "Data" FROM "Pending" pnd, "PendingData" pnddata WHERE pnd."SeqId" =
> pnddata."SeqId" AND pnd."XID"={ } ORDER BY "SeqId", "IsKey" DESC
> 11
> 111.962
> 9068
> SELECT DISTINCT
> name FROM
> tmm_customer_domains WHERE name={ }
> 12
> 73.809
> 3837
> SELECT MIN
> (message_idnr)
> FROM
> dbmail_messages
> WHERE
> mailbox_idnr =
> { } AND status <
> { } AND seen_flag
> = { }
> 13
> 70.220
> 1884
> commit
> 14
> 65.325
> 5948
> SELECT
> block.messageblk
> FROM
> dbmail_messageblks block, dbmail_messages msg WHERE block.physmessage_id =
> msg.physmessage_id AND msg.message_idnr = { } ORDER BY block.messageblk_idnr
> 15
> 60.511
> 45277
> select
> content,ttl,prio,type,domain_id,name from records where type={ } and name={ }
> Slowest queries
> Rank
> Time
> Query text
> 1
> 84.216
> SELECT
> pnd."SeqId",pnd."TableName", pnd."Op",pnddata."IsKey", pnddata."Data" AS
> "Data" FROM "Pending" pnd, "PendingData" pnddata WHERE pnd."SeqId" =
> pnddata."SeqId" AND pnd."XID"={ } ORDER BY "SeqId", "IsKey" DESC
> 2
> 81.209
> SELECT
> pnd."SeqId",pnd."TableName", pnd."Op",pnddata."IsKey", pnddata."Data" AS
> "Data" FROM "Pending" pnd, "PendingData" pnddata WHERE pnd."SeqId" =
> pnddata."SeqId" AND pnd."XID"={ } ORDER BY "SeqId", "IsKey" DESC
> 3
> 57.863
> SELECT seen_flag,
> answered_flag,
> deleted_flag,
> flagged_flag,
> draft_flag,
> recent_flag, TO_CHAR
> (internal_date, { } ),
> rfcsize, message_idnr
> FROM dbmail_messages
> msg, dbmail_physmessage
> pm WHERE pm.id =
> msg.physmessage_id AND
> message_idnr BETWEEN
> { } AND { } AND
> mailbox_idnr = { } AND
> status < { } ORDER BY
> message_idnr ASC
> 4
> 45.004
> SELECT seen_flag,
> answered_flag,
> deleted_flag,
> flagged_flag,
> draft_flag,
> recent_flag, TO_CHAR
> (internal_date, { } ),
> rfcsize, message_idnr
> FROM dbmail_messages
> msg, dbmail_physmessage
> pm WHERE pm.id =
> msg.physmessage_id AND
> message_idnr BETWEEN
> { } AND { } AND
> mailbox_idnr = { } AND
> status < { } ORDER BY
> message_idnr ASC
> 5
> 37.403
> SELECT seen_flag,
> answered_flag,
> deleted_flag,
> flagged_flag,
> draft_flag,
> recent_flag, TO_CHAR
> (internal_date, { } ),
> rfcsize, message_idnr
> FROM dbmail_messages
> msg, dbmail_physmessage
> pm WHERE pm.id =
> msg.physmessage_id AND
> message_idnr BETWEEN
> { } AND { } AND
> mailbox_idnr = { } AND
> status < { } ORDER BY
> message_idnr ASC
> 6
> 32.138
> SELECT seen_flag,
> answered_flag,
> deleted_flag,
> flagged_flag,
> draft_flag,
> recent_flag, TO_CHAR
> (internal_date, { } ),
> rfcsize, message_idnr
> FROM dbmail_messages
> msg, dbmail_physmessage
> pm WHERE pm.id =
> msg.physmessage_id AND
> message_idnr BETWEEN
> { } AND { } AND
> mailbox_idnr = { } AND
> status < { } ORDER BY
> message_idnr ASC
> 7
> 29.513
> SELECT seen_flag,
> answered_flag,
> deleted_flag,
> flagged_flag,
> draft_flag,
> recent_flag, TO_CHAR
> (internal_date, { } ),
> rfcsize, message_idnr
> FROM dbmail_messages
> msg, dbmail_physmessage
> pm WHERE pm.id =
> msg.physmessage_id AND
> message_idnr BETWEEN
> { } AND { } AND
> mailbox_idnr = { } AND
> status < { } ORDER BY
> message_idnr ASC
> 8
> 28.300
> SELECT seen_flag,
> answered_flag,
> deleted_flag,
> flagged_flag,
> draft_flag,
> recent_flag, TO_CHAR
> (internal_date, { } ),
> rfcsize, message_idnr
> FROM dbmail_messages
> msg, dbmail_physmessage
> pm WHERE pm.id =
> msg.physmessage_id AND
> message_idnr BETWEEN
> { } AND { } AND
> mailbox_idnr = { } AND
> status < { } ORDER BY
> message_idnr ASC
> 9
> 20.188
> SELECT usr.user_idnr,
> sum(pm.messagesize),
> usr.curmail_size FROM
> dbmail_users usr LEFT
> JOIN dbmail_mailboxes
> mbx ON mbx.owner_idnr =
> usr.user_idnr LEFT JOIN
> dbmail_messages msg ON
> msg.mailbox_idnr =
> mbx.mailbox_idnr LEFT
> JOIN dbmail_physmessage
> pm ON pm.id =
> msg.physmessage_id AND
> msg.status < { } GROUP
> BY usr.user_idnr,
> usr.curmail_size HAVING
> ((SUM(pm.messagesize)
> <> usr.curmail_size) OR
> (NOT (SUM
> (pm.messagesize) IS NOT
> NULL) AND
> usr.curmail_size <>
> { }))
> 10
> 19.975
> DELETE FROM
> net_packets_raw WHERE
> timestamp < { }
> 11
> 17.378
> SELECT
> filename,md5sum,size,mtime FROM filelist WHERE owner={ } AND filename LIKE {
> } EXCEPT SELECT filename,md5sum,size,mtime FROM filelist WHERE owner={ } AND
> filename LIKE { } ORDER BY filename ASC LIMIT { } OFFSET { }
> 12
> 15.587
> SELECT COUNT
> (message_idnr), COUNT
> (message_idnr) - SUM
> (seen_flag), SUM
> (recent_flag) FROM
> dbmail_messages WHERE
> mailbox_idnr = { } AND
> status < { }
> 13
> 15.554
> SELECT message_idnr
> FROM dbmail_messages
> WHERE mailbox_idnr =
> { } AND status < { }
> ORDER BY message_idnr
> ASC
> 14
> 15.186
> SELECT
> filename,md5sum,size,mtime FROM filelist WHERE owner={ } AND filename LIKE {
> } EXCEPT SELECT filename,md5sum,size,mtime FROM filelist WHERE owner={ } AND
> filename LIKE { } ORDER BY filename ASC LIMIT { } OFFSET { }
> 15
> 14.212
> SELECT
> filename,md5sum,size,mtime FROM filelist WHERE owner={ } AND filename LIKE {
> } EXCEPT SELECT filename,md5sum,size,mtime FROM filelist WHERE owner={ } AND
> filename LIKE { } ORDER BY filename ASC LIMIT { } OFFSET { }
> Most frequent queries
> Rank
> Times executed
> Query text
> 1
> 45277
> select
> content,ttl,prio,type,domain_id,name from records where type={ } and name={ }
> 2
> 41707
> SELECT messageblk FROM
> dbmail_messageblks blk,
> dbmail_messages msg
> WHERE
> blk.physmessage_id =
> msg.physmessage_id AND
> msg.message_idnr = { }
> ORDER BY
> blk.messageblk_idnr ASC
> LIMIT { }
> 3
> 22776
> SELECT no_select FROM
> dbmail_mailboxes WHERE
> mailbox_idnr = { }
> 4
> 20731
> INSERT INTO
> "PendingData" ("SeqId","IsKey","Data") VALUES(currval({ }),{ },$1)
> 5
> 19014
> SELECT owner_idnr FROM
> dbmail_mailboxes WHERE
> mailbox_idnr = { }
> 6
> 18917
> SELECT no_inferiors
> FROM dbmail_mailboxes
> WHERE mailbox_idnr =
> { }
> 7
> 18917
> SELECT name FROM
> dbmail_mailboxes WHERE
> mailbox_idnr = { }
> 8
> 16366
> SELECT mailbox_idnr
> FROM dbmail_mailboxes
> WHERE mailbox_idnr =
> { } AND owner_idnr =
> { }
> 9
> 12984
> INSERT INTO
> "Pending" ("TableName","Op","XID") VALUES ($1,$2,$3)
> 10
> 9593
> SELECT COUNT
> (message_idnr), COUNT
> (message_idnr) - SUM
> (seen_flag), SUM
> (recent_flag) FROM
> dbmail_messages WHERE
> mailbox_idnr = { } AND
> status < { }
> 11
> 9593
> SELECT message_idnr +
> { } FROM
> dbmail_messages ORDER
> BY message_idnr DESC
> LIMIT { }
> 12
> 9593
> SELECT
> permission,seen_flag,answered_flag,deleted_flag,flagged_flag,recent_flag,draft_flag
> FROM dbmail_mailboxes WHERE mailbox_idnr = { }
> 13
> 9526
> SELECT message_idnr
> FROM dbmail_messages
> WHERE mailbox_idnr =
> { } AND status < { }
> ORDER BY message_idnr
> ASC
> 14
> 9154
> SELECT indkey FROM
> pg_index WHERE
> indisprimary={ } AND
> indrelid={ }
> 15
> 9068
> SELECT DISTINCT name
> FROM
> tmm_customer_domains
> WHERE name={ }
> _______________________________________________
> Dbmail-dev mailing list
> [email protected]
> http://twister.fastxs.net/mailman/listinfo/dbmail-dev
--
Internet Connection High Quality Web Hosting
http://www.internetconnection.net/