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]