[EMAIL PROTECTED] wrote:
<snip>
First, THANK YOU VERY MUCH!!! You actually posted the results of SHOW CREATE TABLE and EXPLAIN. I wish everyone who had a query problem would do those two very simple things.

Agreed!

Second, let's look again at what your EXPLAIN is telling you. If you locate the columns "possible_keys" and "key". Both are NULL for both tables in your query. That means that there are no indexes that could possibly cover at least one term in your WHERE clause and that none of them were actually used. The database engine has to perform a full-table scan on both tables to solve the query.

Exactly.

The column `no_viaje` is used in a few keys but in none of them is it the left-most term, so those indexes cannot be used to find tables using just that column. You already have several indexes defined for both tables so I am concerned about slowing down your INSERT speed with this suggestion however to get that query to respond, you need to add another index to one or both tables

ALTER TABLE `trafico_guia` ADD KEY (`no_viaje`, `fecha_guia`);
ALTER TABLE `trafico_viaje` ADD KEY(`no_viaje`);

Either one will speed up your query but adding both will make it fly.

I don't think that's quite right, because I don't think the multi-column index on (no_viaje, fecha_guia) will help.

First, I'll rewrite the query with an explicit join:

  SELECT a.id_unidad,
         b.fecha_guia,
         b.monto_pago*b.monto_tipo_cambio
  FROM trafico_viaje a
  JOIN trafico_guia b
    ON a.no_viaje=b.no_viaje
  WHERE b.fecha_guia BETWEEN '2005/01/01' AND '2005/01/31';

Now, it should be clear that the best way to execute this query is to first select rows in trafico_guia (table b) with the right fecha_guia values, then find corresponding rows in trafico_viaje (table a) where a.no_viaje=b.no_viaje. For fastest execution, we need two things:

1) An index in trafico_guia with fecha_guia as the leftmost part. This will alllow quickly finding the correct rows in b. A single column index is all that's needed, but any multi-column index that starts with fecha_guia would do.

2) An index in trafico_viaje with no_viaje as the leftmost part. This will allow quickly finding matching rows in a for each row found in b. Again, a single column index is all that's needed, but any multi-column index that starts with no_viaje would do.

--

Looking carefully at the two table definitions, I'm a little confused by your key definitions. Three of your primary keys seem to be multi-column indexes on (id_area, no_tablename). As a result, table trafico_guia has 3 keys with id_area as the leftmost part, two of which are needed for foreign key definitions. There is some inefficiency that could be avoided if that redundancy could be removed.

In particular, as it relates to this query, the primary key for table trafico_viaje is (id_area, no_viaje), so table trafico_guia also has an index on (id_area, no_viaje). Your query, however, only uses no_viaje to join the tables! That at least implies that no_viaje would be sufficient as the primary key. Is it the case that the combination of id_area and no_viaje is required to uniquely identify a row in trafico_viaje, or are values of no_viaje unique? If the latter, then the primary key should be a single column index on no_viaje, and area_id should be indexed separately. If that's the case for all three tables, you could add the indexes you need for this query while actually reducing your total index size.

Even if you need both values in your primary key, you may be better off swapping the order. The question is, what do you typically have in your WHERE clauses? The only reason to have id_area first and no_viaje second would be to help queries which require a single area_id and a *range* of no_viaje values. Queries which require a fixed value for each would be helped regardless which column comes first in the index. If the query here is any indication, sometimes you only need to match no_viaje without regard to area_id. In that case, you need no_viaje to come first, or a separate index on no_viaje.

Michael

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

Reply via email to