0

i have a sql like this:

select t1.id,t1.type from collect t1 
 where t1.type='1' and t1.status='1' 
    and t1.total>(t1.totalComplate+t1.totalIng)  
    and id not in(
             select tid from collect_log t2 
              where t2.tid=t1.id and t2.bid='1146') 
limit 1;

is is ok, but its performance seems not very good and if i using a order command:

select t1.id,t1.type from collect t1 
 where t1.type='1' and t1.status='1' 
    and t1.total>(t1.totalComplate+t1.totalIng)  
    and id not in(
             select tid from collect_log t2 
              where t2.tid=t1.id and t2.bid='1146') 
order by t1.id asc 
limit 1;

it become even worse. how can i optimize this?

here is explain:

id | select_type        | table | type | possible_keys | key | key_len | ref             | rows | Extra                       |
+----+--------------------+-------+------+---------------+-----+---------+-----------------+------+-----------------------------+
|  1 | PRIMARY            | t1    | ref  | i2,i1,i3      | i1  | 4       | const,const     |   99 | Using where; Using filesort |
|  2 | DEPENDENT SUBQUERY | t2    | ref  | i5            | i5  | 65      | img.t1.id,const |    2 | Using where; Using index 
4

2 回答 2

1

1) If it's not already done, define an index on the collect.id column :

CREATE INDEX idx_collect_id ON collect (id);

Or possibly a unique index if you can (if id is never the same for any two lines) :

CREATE UNIQUE INDEX idx_collect_id ON collect (id);

Maybe you need an index on collect_log.tid or collect_log.bid, too. Or even on both columns, like so :

CREATE INDEX idx_collect_log_tidbid ON collect (tid, bid);

Make it UNIQUE if it makes sense, that is, if no two lines have the same values for the (tid, bid) couple in the table. For instance if these queries give the same result, it might be possible :

SELECT count(*) FROM collect_log;

SELECT count(DISTINCT tid, bid) FROM collect_log;

But don't make it UNIQUE if you're unsure what it means.

2) Verify the types of the columns collect.type, collect.status and collect_log.bid. In your query, you are comparing them with strings, but maybe they are defined as INT (or SMALLINT or TINYINT...) ? In this case I advise you to drop the quotes around the numbers, because string comparisons are painfully slow compared to integer comparisons.

select t1.id,t1.type from collect t1 
 where t1.type=1 and t1.status=1 
    and t1.total>(t1.totalComplate+t1.totalIng)  
    and id not in(
             select tid from collect_log t2 
              where t2.tid=t1.id and t2.bid=1146) 
order by t1.id asc 
limit 1;

3) If that still doesn't help, just add EXPLAIN in front of your query, and you'll get the execution plan. Paste the results here and we can help you make some sense out of it. Actually, I would advise you to do this step before creating any new index.

于 2013-07-23T09:23:21.637 回答
-1

I'd try to get rid of the IN statement using an INNER LEFT JOIN first.

Something like this (untested):

select t1.id,t1.type 
from collect t1 
    LEFT JOIN collect_log t2 ON t1.id = t2.tid
where t1.type='1' 
    and t1.status='1' 
    and t1.total>(t1.totalComplate+t1.totalIng)  
    and NOT t2.bid = '1146'
order by t1.id asc 
limit 1;
于 2013-07-23T08:47:46.157 回答