Hi.

On Thu 2002-07-25 at 10:49:47 -0500, [EMAIL PROTECTED] wrote:
> Hi, I have a problem where the index for a SET column does not get used 
> once I link in another table.
> 
> The output to explain:
> 
> mysql> explain select count(*) from NS_articles where 
> find_in_set('approved', artFlags) > 0; 
> 
> 
>+-------------+-------+---------------+----------+---------+------+------+-------------------------+
> | table       | type  | possible_keys | key      | key_len | ref  | rows 
> | Extra                   |
> 
>+-------------+-------+---------------+----------+---------+------+------+-------------------------+
> | NS_articles | index | NULL          | artFlags |       2 | NULL |  560 
> | where used; Using index |
> 
>+-------------+-------+---------------+----------+---------+------+------+-------------------------+
> 
> This is good, the index on artFlags is being used. Now I link in another 
> table:

No, the index is not really used (possible_keys = NULL), because you
have an expression (FIND_IN_SET()) instead of a column and MySQL
cannot indexes on (most/any?) expressions. I.e. it is not used to find
the rows based on an index lookup, but MySQL sees that you are only
interested in column(s) from an index and therefore reads in the
index, instead of the data file ("using index"). Well, in hindsight,
"using index" surely was not best choice to describe that behaviour.

To make that more clear. Imagine you have 1.000.000 rows, 100 bytes
each.  An index on the column of interest needs 10 bytes per row.
Looking up 200 rows of a range without index, reads the whole table
(i.e. the data file): about 1.000.000 * 100 bytes = ~100MB.

Reading them using only the index file ("using index") reads 1/10th of
that (10 bytes instead of 100 bytes per row), i.e. 10MB and one can
assume that this will also be faster about 10 times (this is specific
to this example, of course). That is why MySQL does this in your case.

Really making use of the index for the lookup, needs about 1 index
lookup for the first row, reading log2(1.000.000) =~ 20 index pages
(each 1KB usually) plus the 199 remaining rows, each 100 bytes, or 19
index pages (10 fitting in one 1KB page; in reality, it's less, let's
say 5). I did not consider the data file intentionally ("using index"
additionally, you know). So it reads less than 60KB, but needs
additional 20 disk seeks. That would be real good! ;-)

> mysql> explain select count(*) searchTotal from NS_articles nsa, 
> NS_editors nse where  find_in_set('approved', nsa.artFlags) > 0 and 
> nsa.artEditor = nse.id;
> +-------+-------+---------------+-----------+---------+--------+------+-------------+
> | table | type  | possible_keys | key       | key_len | ref    | rows | 
> Extra       |
> +-------+-------+---------------+-----------+---------+--------+------+-------------+
> | nse   | index | PRIMARY       | PRIMARY   |      32 | NULL   |   21 | 
> Using index |
> | nsa   | ref   | artEditor     | artEditor |      32 | nse.id |   19 | 
> where used  |
> +-------+-------+---------------+-----------+---------+--------+------+-------------+
> 
> What happened to the index on artFlags? The table link uses indexes 
> which is good, but now artFlags is doing a raw table scan.

I presume it is because you do not have any key in NS_articles which
covers both, id and artFlags. I.e. for "using index" you would need a
combined key (id, artFlags).

But as explained above, you should get the real speed boost if you can
somehow manage to avoid the expression instead of only the column
name. Unfortuneately, that is not possible in the common case. If you
query very often based on this 'approved' flag, you may want to
consider to give it an own column (which should use indexes
appropriately).

For more details, see the manual sections about index usage and
optimization.

Greetings,

        Benjamin.


-- 
[EMAIL PROTECTED]

---------------------------------------------------------------------
Before posting, please check:
   http://www.mysql.com/manual.php   (the manual)
   http://lists.mysql.com/           (the list archive)

To request this thread, e-mail <[EMAIL PROTECTED]>
To unsubscribe, e-mail <[EMAIL PROTECTED]>
Trouble unsubscribing? Try: http://lists.mysql.com/php/unsubscribe.php

Reply via email to