0

I have the following Table:

  CREATE TABLE `sal_forwarding` (
  `sid` BIGINT(20) UNSIGNED NOT NULL AUTO_INCREMENT,
  `f_shop` INT(11) NOT NULL,
  `f_offer` INT(11) DEFAULT NULL,
  .
  .
  .
  PRIMARY KEY (`sid`),
  KEY `forwardTime` (`forwardTime`,`f_shop`),
  KEY `forwardTime_2` (`forwardTime`),
  KEY `f_shop` (`f_shop`)
) ENGINE=INNODB AUTO_INCREMENT=10457068 DEFAULT CHARSET=latin1

This table has more than 5 million rows.

I've set indexes, as you can see above, but in my query no indexes are used and I don't understand why. Does anybody see my problem?

Explain:

EXPLAIN SELECT 
  f_shop
  , COUNT(sid)
  , SUM(IF(toolbarUser=1,1,0)) 
FROM sal_forwarding 
WHERE DATE(forwardTime) = "2011-09-01" 
GROUP BY f_shop

Result:

+----+-------------+----------------+-------+---------------+--------+---------+--------+--------+-------------+
| ID | SELECT_TYPE |     TABLE      | TYPE  | POSSIBLE_KEYS |  KEY   | KEY_LEN |  REF   |  ROWS  |    EXTRA    |
+----+-------------+----------------+-------+---------------+--------+---------+--------+--------+-------------+
|    |             |                |       |               |        |         |        |        |             |
| 1  | SIMPLE      | sal_forwarding | index | (NULL)        | f_shop | 4       | (NULL) | 232449 | Using where |
+----+-------------+----------------+-------+---------------+--------+---------+--------+--------+-------------+
3
  • When I changed the query to:EXPLAIN SELECT f_shop, COUNT(sid), SUM(IF(toolbarUser=1,1,0)) FROM sal_forwarding GROUP BY f_shop. No Index is used too. I removed the DATE() function and no index is used. :( Commented Sep 27, 2011 at 11:08
  • @dnagirl, you have the correct answer, why did you delete it? Commented Sep 27, 2011 at 12:32
  • As a newbie, you may want to start accepting answers to your questions for the solutions found. This way, it gives credit to those helping, and others will continue to help in the future... look for the check mark to the left of the answers and check whichever was the solution. It also helps others from searching for older questions to still try and offer solutions when they are already long-ago solved. Commented Oct 10, 2011 at 12:40

1 Answer 1

2

MySQL cannot use an index on a column inside a function.
Remove the function date() from your select and MySQL will use the index.

You can do this by changing your column definition of forwardtime to DATE
Or you can change the query like so

SELECT 
  f_shop
  , COUNT(*) as RowCount
  , SUM(toolbarUser=1) as NumberOfToolbarUsers
FROM sal_forwarding 
WHERE forwardTime BETWEEN '2011-09-01 00:00' AND '2011-09-01 23:59' 
GROUP BY f_shop

Remarks

  • count(*) is faster than count(namedcolumn);
  • (a=1) => 1 if true, (a=1) => 0 if false, so the if(a=1,1,0) can be shortened;
  • It's a good idea to alias your aggregate columns, so you can refer to them by their alias later.
  • If you add the following index (and remove index forwardtime), you query will run even faster. KEY fasttime (forwardTime,f_shop,toolbarUser)
  • The previous point is especially true on InnoDB where MySQL will use a covering index if possible, which means that it will never read the table itself to retrieve the data if it can find all it needs in the index.
Sign up to request clarification or add additional context in comments.

5 Comments

Perhaps you can add that a (f_shop, forwardTime) index will help.
Or an (forwardTime) one, depending on distribution.
@ypercube, You are still accessing toolbaruser, so I doubt that will make much difference.
That check is done only in the rows that pass the WHERE condition. The best way I think would be if forwardTime was a date column and an index of (forwardTime,f_shop,toolbarUser) was used.
@ypercube, you are correct, I'll add that to the answer thanks.

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.