In general, I try to stay away from very large IN(..) lists because I have seen them regularly degrade performance, but in this case the alternative that I have found doesn't seem to perform any faster. Could anyone give me some insight as to which of the following queries is "better" (and why) - or if there is another query that would be faster than either?

I am using MySQL 4.1.14. There are three tables,

offers:
CREATE TABLE `offers` (
 `offer_id` int(11) NOT NULL auto_increment,
 `advertiser_id` int(11) NOT NULL default '0',
...
 PRIMARY KEY  (`offer_id`),
 KEY `advertiser_id` (`advertiser_id`)
)

paytable:
CREATE TABLE `paytable` (
 `offer_id` int(11) NOT NULL default '0',
 `login_id` int(11) NOT NULL default '0',
...
 PRIMARY KEY  (`offer_id`,`login_id`)
)

publisher_advertiser_blocks:
CREATE TABLE `publisher_advertiser_blocks` (
 `login_id` int(11) NOT NULL default '0',
 `advertiser_id` int(11) NOT NULL default '0',
 PRIMARY KEY  (`login_id`,`advertiser_id`)
)

The goal of these queries is to select all offer_id's from `paytable` for a known login_id where that login_id is not "blocked" from that offer_id. While testing I simply selected count(*) to keep my result set from crowding the screen.

The two queries have about the same execution time but very different EXPLAIN results... without further ado, here they are:

explain
select count(*) from paytable
where login_id=#
and offer_id NOT IN
(
select distinct offer_id
from offers
left join publisher_advertiser_blocks pab
using (advertiser_id)
where pab.login_id=#
);

+----+--------------------+----------+--------+-----------------------+---------+---------+--------------------------------------+---------+-----------------------------
-+
| id | select_type | table | type | possible_keys | key | key_len | ref | rows | Extra |
+----+--------------------+----------+--------+-----------------------+---------+---------+--------------------------------------+---------+-----------------------------
-+
| 1 | PRIMARY | paytable | index | NULL | PRIMARY | 5 | NULL | 1773152 | Using where; Using index | | 2 | DEPENDENT SUBQUERY | offers | eq_ref | PRIMARY,advertiser_id | PRIMARY | 4 | func | 1 | Using where; Using temporary
|
| 2 | DEPENDENT SUBQUERY | pab | eq_ref | PRIMARY | PRIMARY | 8 | const,affiliate.offers.advertiser_id | 1 | Using where; Using index |
+----+--------------------+----------+--------+-----------------------+---------+---------+--------------------------------------+---------+-----------------------------
-+
3 rows in set (0.00 sec)



explain
select count(*)
from paytable
left join
(
select distinct offer_id
from offers
left join publisher_advertiser_blocks pab
using (advertiser_id)
where pab.login_id=#
) as a using (offer_id)
where login_id=# and a.offer_id IS NULL;
+----+-------------+------------+-------+---------------+---------------+---------+-----------------------------+---------+-------------------------------------------+
| id | select_type | table | type | possible_keys | key | key_len | ref | rows | Extra |
+----+-------------+------------+-------+---------------+---------------+---------+-----------------------------+---------+-------------------------------------------+
| 1 | PRIMARY | paytable | index | NULL | PRIMARY | 5 | NULL | 1773152 | Using where; Using index | | 1 | PRIMARY | <derived2> | ALL | NULL | NULL | NULL | NULL | 309 | Using where; Not exists | | 2 | DERIVED | pab | ref | PRIMARY | PRIMARY | 4 | | 2 | Using where; Using index; Using temporary | | 2 | DERIVED | offers | ref | advertiser_id | advertiser_id | 2 | affiliate.pab.advertiser_id | 8 | Using where |
+----+-------------+------------+-------+---------------+---------------+---------+-----------------------------+---------+-------------------------------------------+
4 rows in set (0.01 sec)



Thanks in advance,

--
Devananda vdv


http://devananda-vdv.blogspot.com/
http://mycat.sourceforge.net/


--
MySQL General Mailing List
For list archives: http://lists.mysql.com/mysql
To unsubscribe:    http://lists.mysql.com/[EMAIL PROTECTED]

Reply via email to