On Fri, Aug 22, 2003 at 10:07:46AM -0700, Steven Roussey wrote:
> Hmmm, just in case you can't change the table layout...
> 
> Run this through MySQL. First I get rid of the other index I made, then
> add chained indexes so there is no need for data file lookup. Also, one
> direction of the query table join chain was not always using the indexes
> for the where. One direction is preferable (not knowing what the data
> is) since then we can use the index for the sort, but the other
> direction may have benefits that outweigh that, so that is why we used
> the composite index I last suggested. 

My previous message should have helped to clarify what's going
on here, and why I used the structures I did.

> Anyhow, just to be clear, lets force all composite indexes for this
> query in both direction and force the optimizer to use both directions
> and see what we get (and sorry if I misspell or something, since I don't
> have your DB to check against). Run this and send back the results:
> 
> 
> # Get rid of the index I added before
> ALTER TABLE cg DROP INDEX q_id_2;
> 
> 
> # Get a baseline for direction 1
> SELECT STRAIGHT_JOIN cg.cw FROM cg,q,cit,sref
> WHERE cg.q_id = q.id AND q.cit_id = cit.id AND cit.sref_id = sref.id
> AND cg.cw LIKE 't%'
> AND sref.cd > DATE_SUB(CURDATE(), INTERVAL 6 MONTH)
> ORDER BY cg.cw
> LIMIT 1000,10;

This took the same 1 m 15 sec the first time, and on an
immediately succeeding run, the same 3.5 sec.

> EXPLAIN SELECT STRAIGHT_JOIN cg.cw FROM cg,q,cit,sref
> WHERE cg.q_id = q.id AND q.cit_id = cit.id AND cit.sref_id = sref.id
> AND cg.cw LIKE 't%'
> AND sref.cd > DATE_SUB(CURDATE(), INTERVAL 6 MONTH)
> ORDER BY cg.cw
> LIMIT 1000,10;

*************************** 1. row ***************************
        table: cg
         type: range
possible_keys: q_id,cw
          key: cw
      key_len: 101
          ref: NULL
         rows: 190550
        Extra: Using where
*************************** 2. row ***************************
        table: q
         type: eq_ref
possible_keys: PRIMARY,cit_id
          key: PRIMARY
      key_len: 4
          ref: cg.q_id
         rows: 1
        Extra: 
*************************** 3. row ***************************
        table: cit
         type: eq_ref
possible_keys: PRIMARY,sref_id
          key: PRIMARY
      key_len: 4
          ref: q.cit_id
         rows: 1
        Extra: 
*************************** 4. row ***************************
        table: sref
         type: eq_ref
possible_keys: PRIMARY,cd
          key: PRIMARY
      key_len: 4
          ref: cit.sref_id
         rows: 1
        Extra: Using where
4 rows in set (0.00 sec)

> # Get a baseline for direction 2
> SELECT STRAIGHT_JOIN cg.cw FROM sref,cit,q,cg
> WHERE cg.q_id = q.id AND q.cit_id = cit.id AND cit.sref_id = sref.id
> AND cg.cw LIKE 't%'
> AND sref.cd > DATE_SUB(CURDATE(), INTERVAL 6 MONTH)
> ORDER BY cg.cw
> LIMIT 1000,10;

This took 2.7 sec the first time, and 2.4 sec after. Getting better.

> EXPLAIN SELECT STRAIGHT_JOIN cg.cw FROM sref,cit,q,cg
> WHERE cg.q_id = q.id AND q.cit_id = cit.id AND cit.sref_id = sref.id
> AND cg.cw LIKE 't%'
> AND sref.cd > DATE_SUB(CURDATE(), INTERVAL 6 MONTH)
> ORDER BY cg.cw
> LIMIT 1000,10;

*************************** 1. row ***************************
        table: sref
         type: range
possible_keys: PRIMARY,cd
          key: cd
      key_len: 4
          ref: NULL
         rows: 3102
        Extra: Using where; Using temporary; Using filesort
*************************** 2. row ***************************
        table: cit
         type: ref
possible_keys: PRIMARY,sref_id
          key: sref_id
      key_len: 4
          ref: sref.id
         rows: 3
        Extra: 
*************************** 3. row ***************************
        table: q
         type: ref
possible_keys: PRIMARY,cit_id
          key: cit_id
      key_len: 4
          ref: cit.id
         rows: 31
        Extra: 
*************************** 4. row ***************************
        table: cg
         type: ref
possible_keys: q_id,cw
          key: q_id
      key_len: 4
          ref: q.id
         rows: 1
        Extra: Using where

I note there's the temporary _and_ filesort for the sref section.

> # add indexes
> ALTER TABLE cg 
> ADD INDEX dir1(cw,q_id), 
> ADD INDEX dir2(q_id,cw);
>
> ALTER TABLE q 
> ADD INDEX dir1(id,cit_id), 
> ADD INDEX dir2(cit_id,id);
> 
> ALTER TABLE cit 
> ADD INDEX dir1(id,sref_id), 
> ADD INDEX dir2(sref_id,id);
> 
> ALTER TABLE sref 
> ADD INDEX dir1(id,cd), 
> ADD INDEX dir2(cd,id);
> 
> 
> # Get a new result for direction 1
> SELECT STRAIGHT_JOIN cg.cw FROM 
> cg USE INDEX(dir1),
> q USE INDEX(dir1),
> cit USE INDEX(dir1),
> sref USE INDEX(dir1)
> WHERE cg.q_id = q.id AND q.cit_id = cit.id AND cit.sref_id = sref.id
> AND cg.cw LIKE 't%'
> AND sref.cd > DATE_SUB(CURDATE(), INTERVAL 6 MONTH)
> ORDER BY cg.cw
> LIMIT 1000,10;

This took 7.86 sec first, and then 2.30 sec.

> EXPLAIN SELECT STRAIGHT_JOIN cg.cw FROM 
> cg USE INDEX(dir1),
> q USE INDEX(dir1),
> cit USE INDEX(dir1),
> sref USE INDEX(dir1)
> WHERE cg.q_id = q.id AND q.cit_id = cit.id AND cit.sref_id = sref.id
> AND cg.cw LIKE 't%'
> AND sref.cd > DATE_SUB(CURDATE(), INTERVAL 6 MONTH)
> ORDER BY cg.cw
> LIMIT 1000,10;

+-------+-------+---------------+------+---------+-------------+--------+--------------------------+
| table | type  | possible_keys | key  | key_len | ref         | rows   | Extra        
            |
+-------+-------+---------------+------+---------+-------------+--------+--------------------------+
| cg    | range | dir1          | dir1 |     101 | NULL        | 179078 | Using where; 
Using index |
| q     | ref   | dir1          | dir1 |       4 | cg.q_id     |      1 | Using index  
            |
| cit   | ref   | dir1          | dir1 |       4 | q.cit_id    |      1 | Using index  
            |
| sref  | ref   | dir1          | dir1 |       4 | cit.sref_id |      1 | Using where; 
Using index |
+-------+-------+---------------+------+---------+-------------+--------+--------------------------+

Oops, sorry about spacing.

> # Get a new result for direction 2
> SELECT STRAIGHT_JOIN cg.cw FROM 
> sref USE INDEX(dir2),
> cit USE INDEX(dir2),
> q USE INDEX(dir2),
> cg USE INDEX(dir2)
> WHERE cg.q_id = q.id AND q.cit_id = cit.id AND cit.sref_id = sref.id
> AND cg.cw LIKE 't%'
> AND sref.cd > DATE_SUB(CURDATE(), INTERVAL 6 MONTH)
> ORDER BY cg.cw
> LIMIT 1000,10;

This took 3.15 sec and then 2.89 sec.

I note that in both cases, there isn't a drastic difference
between what we had before the composite indexes, despite all
of this effort.

> EXPLAIN SELECT STRAIGHT_JOIN cg.cw FROM 
> sref USE INDEX(dir2),
> cit USE INDEX(dir2),
> q USE INDEX(dir2),
> cg USE INDEX(dir2)
> WHERE cg.q_id = q.id AND q.cit_id = cit.id AND cit.sref_id = sref.id
> AND cg.cw LIKE 't%'
> AND sref.cd > DATE_SUB(CURDATE(), INTERVAL 6 MONTH)
> ORDER BY cg.cw
> LIMIT 1000,10;

*************************** 1. row ***************************
        table: sref
         type: range
possible_keys: dir2
          key: dir2
      key_len: 4
          ref: NULL
         rows: 1806
        Extra: Using where; Using index; Using temporary; Using filesort
*************************** 2. row ***************************
        table: cit
         type: ref
possible_keys: dir2
          key: dir2
      key_len: 4
          ref: sref.id
         rows: 3
        Extra: Using index
*************************** 3. row ***************************
        table: q
         type: ref
possible_keys: dir2
          key: dir2
      key_len: 4
          ref: cit.id
         rows: 31
        Extra: Using index
*************************** 4. row ***************************
        table: cg
         type: ref
possible_keys: dir2
          key: dir2
      key_len: 4
          ref: q.id
         rows: 1
        Extra: Using where; Using index

Hmm. Looks like fewer rows, but with both temporary and filesort
on sref, and no huge speed difference.

Well, there you go--thanks again for looking over this so closely!

Best,

Jesse

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

Reply via email to