Login | Register For Free | Help
Search for: (Advanced)

Mailing List Archive: DBMail: dev

db.c/db_getmailbox_count - unions not using indexes correctly

 

 

DBMail dev RSS feed   Index | Next | Previous | View Threaded


dbmail-dev at tech

Apr 28, 2008, 7:30 AM

Post #1 of 6 (306 views)
Permalink
db.c/db_getmailbox_count - unions not using indexes correctly

Hi guys,

I'm running dbmail 2.2.10 on ubuntu (installed from source) with mysql
5.0.38. I have mysql set to log queries without indexes to the slow log.

I'm literally getting bombarded with these:
> # Time: 080428 15:22:04
> # User[at]Host: dbmail[dbmail] @ localhost []
> # Query_time: 0 Lock_time: 0 Rows_sent: 3 Rows_examined: 453
> SELECT 'a',COUNT(*) FROM dbmail_messages WHERE mailbox_idnr=163 AND
> (status < 2) UNION SELECT 'b',COUNT(*) FROM dbmail_messages WHERE
> mailbox_idnr=163 AND (status < 2) AND seen_flag=1 UNION SELECT
> 'c',COUNT(*) FROM dbmail_messages WHERE mailbox_idnr=163 AND (status <
> 2) AND recent_flag=1;
> # User[at]Host: dbmail[dbmail] @ localhost []
> # Query_time: 0 Lock_time: 0 Rows_sent: 3 Rows_examined: 111
> SELECT 'a',COUNT(*) FROM dbmail_messages WHERE mailbox_idnr=467 AND
> (status < 2) UNION SELECT 'b',COUNT(*) FROM dbmail_messages WHERE
> mailbox_idnr=467 AND (status < 2) AND seen_flag=1 UNION SELECT
> 'c',COUNT(*) FROM dbmail_messages WHERE mailbox_idnr=467 AND (status <
> 2) AND recent_flag=1;
> # User[at]Host: dbmail[dbmail] @ localhost []
> # Query_time: 0 Lock_time: 0 Rows_sent: 3 Rows_examined: 2937
> SELECT 'a',COUNT(*) FROM dbmail_messages WHERE mailbox_idnr=145 AND
> (status < 2) UNION SELECT 'b',COUNT(*) FROM dbmail_messages WHERE
> mailbox_idnr=145 AND (status < 2) AND seen_flag=1 UNION SELECT
> 'c',COUNT(*) FROM dbmail_messages WHERE mailbox_idnr=145 AND (status <
> 2) AND recent_flag=1;
> # User[at]Host: dbmail[dbmail] @ localhost []
> # Query_time: 0 Lock_time: 0 Rows_sent: 3 Rows_examined: 21
> SELECT 'a',COUNT(*) FROM dbmail_messages WHERE mailbox_idnr=246 AND
> (status < 2) UNION SELECT 'b',COUNT(*) FROM dbmail_messages WHERE
> mailbox_idnr=246 AND (status < 2) AND seen_flag=1 UNION SELECT
> 'c',COUNT(*) FROM dbmail_messages WHERE mailbox_idnr=246 AND (status <
> 2) AND recent_flag=1;
> # User[at]Host: dbmail[dbmail] @ localhost []
> # Query_time: 0 Lock_time: 0 Rows_sent: 3 Rows_examined: 147
> SELECT 'a',COUNT(*) FROM dbmail_messages WHERE mailbox_idnr=144 AND
> (status < 2) UNION SELECT 'b',COUNT(*) FROM dbmail_messages WHERE
> mailbox_idnr=144 AND (status < 2) AND seen_flag=1 UNION SELECT
> 'c',COUNT(*) FROM dbmail_messages WHERE mailbox_idnr=144 AND (status <
> 2) AND recent_flag=1;
> # User[at]Host: dbmail[dbmail] @ localhost []
> # Query_time: 0 Lock_time: 0 Rows_sent: 3 Rows_examined: 3
> SELECT 'a',COUNT(*) FROM dbmail_messages WHERE mailbox_idnr=66 AND
> (status < 2) UNION SELECT 'b',COUNT(*) FROM dbmail_messages WHERE
> mailbox_idnr=66 AND (status < 2) AND seen_flag=1 UNION SELECT
> 'c',COUNT(*) FROM dbmail_messages WHERE mailbox_idnr=66 AND (status <
> 2) AND recent_flag=1;
> # User[at]Host: dbmail[dbmail] @ localhost []
> # Query_time: 0 Lock_time: 0 Rows_sent: 3 Rows_examined: 3
> SELECT 'a',COUNT(*) FROM dbmail_messages WHERE mailbox_idnr=64 AND
> (status < 2) UNION SELECT 'b',COUNT(*) FROM dbmail_messages WHERE
> mailbox_idnr=64 AND (status < 2) AND seen_flag=1 UNION SELECT
> 'c',COUNT(*) FROM dbmail_messages WHERE mailbox_idnr=64 AND (status <
> 2) AND recent_flag=1;

mailbox_idnr=163 AND (status < 2) UNION SELECT 'b',COUNT(*) FROM
dbmail_messages WHERE mailbox_idnr=163 AND (status < 2) AND seen_flag=1
UNION SELECT 'c',COUNT(*) FROM dbmail_messages WHERE mailbox_idnr=163
AND (status < 2) AND recent_flag=1;
+----+--------------+-----------------+-------+----------------------------------------------------------------+----------------+---------+------+------+--------------------------+
| id | select_type | table | type |
possible_keys |
key | key_len | ref | rows | Extra |
+----+--------------+-----------------+-------+----------------------------------------------------------------+----------------+---------+------+------+--------------------------+
| 1 | PRIMARY | dbmail_messages | range |
mailbox_idnr_index,status_index,mailbox_status |
mailbox_status | 9 | NULL | 49 | Using where; Using index |
| 2 | UNION | dbmail_messages | range |
mailbox_idnr_index,seen_flag_index,status_index,mailbox_status |
mailbox_status | 9 | NULL | 49 | Using where |
| 3 | UNION | dbmail_messages | range |
mailbox_idnr_index,status_index,mailbox_status |
mailbox_status | 9 | NULL | 49 | Using where |
| NULL | UNION RESULT | <union1,2,3> | ALL |
NULL |
NULL | NULL | NULL | NULL | |
+----+--------------+-----------------+-------+----------------------------------------------------------------+----------------+---------+------+------+--------------------------+

The function which handles this is int db_getmailbox_count() within
db.c, i'm thinking is it worth having 3 separate smaller queries that
will use the indexes properly rather than a single query with unions ?
It'll be a fairly easy change, i'm happy to write a patch?

The code is currently:
> /* count messages */
> snprintf(query, DEF_QUERYSIZE,
> "SELECT 'a',COUNT(*) FROM %smessages WHERE
> mailbox_idnr=%llu "
> "AND (status < %d) UNION "
> "SELECT 'b',COUNT(*) FROM %smessages WHERE
> mailbox_idnr=%llu "
> "AND (status < %d) AND seen_flag=1 UNION "
> "SELECT 'c',COUNT(*) FROM %smessages WHERE
> mailbox_idnr=%llu "
> "AND (status < %d) AND recent_flag=1",
> DBPFX, mb->uid, MESSAGE_STATUS_DELETE, //
> MESSAGE_STATUS_NEW, MESSAGE_STATUS_SEEN,
> DBPFX, mb->uid, MESSAGE_STATUS_DELETE, //
> MESSAGE_STATUS_NEW, MESSAGE_STATUS_SEEN,
> DBPFX, mb->uid, MESSAGE_STATUS_DELETE); //
> MESSAGE_STATUS_NEW, MESSAGE_STATUS_SEEN);
>
> if (db_query(query) == -1) {
> TRACE(TRACE_ERROR, "query error");
> return DM_EQUERY;
> }
>
> if (db_num_rows()) {
> exists = (unsigned)db_get_result_int(0,1);
> seen = (unsigned)db_get_result_int(1,1);
> recent = (unsigned)db_get_result_int(2,1);
> }
>
> mb->exists = exists;
> mb->unseen = exists - seen;
> mb->recent = recent;


What do you think?

Simon
_______________________________________________
Dbmail-dev mailing list
Dbmail-dev[at]dbmail.org
http://twister.fastxs.net/mailman/listinfo/dbmail-dev


paul at nfg

Apr 28, 2008, 7:46 AM

Post #2 of 6 (295 views)
Permalink
Re: db.c/db_getmailbox_count - unions not using indexes correctly [In reply to]

Simon Gray wrote:
>> # Query_time: 0 Lock_time: 0 Rows_sent: 3 Rows_examined: 3

> What do you think?

Since the Query_time is 0 seconds, what is the problem? I'm not saying the
situation can't be improved, but I seriously doubt splitting the query will do
the job.


--
________________________________________________________________
Paul Stevens paul at nfg.nl
NET FACILITIES GROUP GPG/PGP: 1024D/11F8CD31
The Netherlands________________________________http://www.nfg.nl
_______________________________________________
Dbmail-dev mailing list
Dbmail-dev[at]dbmail.org
http://twister.fastxs.net/mailman/listinfo/dbmail-dev


dbmail-dev at tech

Apr 29, 2008, 3:13 AM

Post #3 of 6 (288 views)
Permalink
Re: db.c/db_getmailbox_count - unions not using indexes correctly [In reply to]

Paul J Stevens wrote:
> Since the Query_time is 0 seconds, what is the problem? I'm not saying the
> situation can't be improved, but I seriously doubt splitting the query will do
> the job.
Agreed, it isn't a problem at the moment, but we're adding more and more
imap users each with many gb mailboxes - Its just that I can see this
becoming an issue in the future.

Simon

_______________________________________________
Dbmail-dev mailing list
Dbmail-dev[at]dbmail.org
http://twister.fastxs.net/mailman/listinfo/dbmail-dev


johnml at gufonero

Apr 29, 2008, 11:04 PM

Post #4 of 6 (284 views)
Permalink
Re: db.c/db_getmailbox_count - unions not using indexes correctly [In reply to]

-----BEGIN PGP SIGNED MESSAGE-----
Hash: SHA1

Simon Gray wrote:
| Paul J Stevens wrote:
|> Since the Query_time is 0 seconds, what is the problem? I'm not saying
|> the
|> situation can't be improved, but I seriously doubt splitting the query
|> will do
|> the job.
| Agreed, it isn't a problem at the moment, but we're adding more and more
| imap users each with many gb mailboxes - Its just that I can see this
| becoming an issue in the future.
|
| Simon
Simon

I doubt that splitting the queries will change whether an index is used.
The potential index on mailbox_idnr is not a good one when there are
many rows corresponding to mailbox_idnr.

Did you try to explain the separated queries? The behaviour should be
the same as in the combined select.

John
-----BEGIN PGP SIGNATURE-----
Version: GnuPG v2.0.4-svn0 (GNU/Linux)
Comment: Using GnuPG with SUSE - http://enigmail.mozdev.org

iD8DBQFIGAvRd4I3jTtt9EIRAgrmAJ9RWxOkuc3pCZN1qmzlQxc41jeqZQCgmqlL
QdsaWIqhtFTzVtPao4CQAks=
=bH5c
-----END PGP SIGNATURE-----
_______________________________________________
Dbmail-dev mailing list
Dbmail-dev[at]dbmail.org
http://twister.fastxs.net/mailman/listinfo/dbmail-dev


dbmail-dev at tech

May 1, 2008, 3:53 PM

Post #5 of 6 (272 views)
Permalink
Re: db.c/db_getmailbox_count - unions not using indexes correctly [In reply to]

John Fawcett wrote:
> Simon
>
> I doubt that splitting the queries will change whether an index is used.
> The potential index on mailbox_idnr is not a good one when there are
> many rows corresponding to mailbox_idnr.
>
> Did you try to explain the separated queries? The behaviour should be
> the same as in the combined select.
>
> John
John,

It doesn't actually use the mailbox_idnr key (at least not in my
environment) it is using the mailbox_status instead. I think the problem
relies within mysql rather than dbmail here, mysql will internally use
its temptable algorithm on unions like this.

http://bugs.mysql.com/bug.php?id=29244

You are correct, the behaviour is the same on each individual query
except the union result part.

Simon
_______________________________________________
Dbmail-dev mailing list
Dbmail-dev[at]dbmail.org
http://twister.fastxs.net/mailman/listinfo/dbmail-dev


johnml at gufonero

May 2, 2008, 10:22 AM

Post #6 of 6 (270 views)
Permalink
Re: db.c/db_getmailbox_count - unions not using indexes correctly [In reply to]

-----BEGIN PGP SIGNED MESSAGE-----
Hash: SHA1

Simon Gray wrote:
| John Fawcett wrote:
|> Simon
|>
|> I doubt that splitting the queries will change whether an index is used.
|> The potential index on mailbox_idnr is not a good one when there are
|> many rows corresponding to mailbox_idnr.
|>
|> Did you try to explain the separated queries? The behaviour should be
|> the same as in the combined select.
|>
|> John
| John,
|
| It doesn't actually use the mailbox_idnr key (at least not in my
| environment) it is using the mailbox_status instead. I think the problem
| relies within mysql rather than dbmail here, mysql will internally use
| its temptable algorithm on unions like this.
|
| http://bugs.mysql.com/bug.php?id=29244
|
| You are correct, the behaviour is the same on each individual query
| except the union result part.
|
Simon
also, if you try an explain of the query on a mailbox with few messages,
mysql will use the index on mailbox_idnr because (presumably) that
is a better policy than range scan on mailbox_status if there are
few matching index rows.
John
-----BEGIN PGP SIGNATURE-----
Version: GnuPG v2.0.4-svn0 (GNU/Linux)
Comment: Using GnuPG with SUSE - http://enigmail.mozdev.org

iD8DBQFIG03Md4I3jTtt9EIRAkJ0AJ0TTAF0CVVvogiFg8WexT8dxomUvQCgnQxv
H2ucd1WiysGDPfVGTQxRf3M=
=prGy
-----END PGP SIGNATURE-----
_______________________________________________
Dbmail-dev mailing list
Dbmail-dev[at]dbmail.org
http://twister.fastxs.net/mailman/listinfo/dbmail-dev

DBMail dev RSS feed   Index | Next | Previous | View Threaded
 
 


Interested in having your list archived? Contact lists@gossamer-threads.com
 
  Web Applications & Managed Hosting Powered by Gossamer Threads Inc.