Forum Moderators: open
When I do a:
"select count(primary) from table where field1 = 1".
The query is extremely fast: 0.06 sec.
When I do a:
"select count(primary) from table where field2 = 1".
The query is extremely fast: 0.04 sec.
When I do a:
"select count(primary) from table where field3 = 1".
The query is extremely fast: 0.00 sec.
So far, everything is OK.
Now, another query:
"select count(primary) from table where field1 = 1 or field2 = 1 or field3 = 1".
This query is slow: 1.96 sec
Why is this query that slow? Any comments?
mysql> SELECT * FROM tbl_name WHERE col1=val1 AND col2=val2;If a multiple-column index exists on col1 and col2, the appropriate rows can be fetched directly. If separate single-column indexes exist on col1 and col2, the optimizer tries to find the most restrictive index by deciding which index finds fewer rows and using that index to fetch the rows.
There's more on that page on this topic...
What does "EXPLAIN select count(primary) from table where field1 = 1 or field2 = 1 or field3 = 1" say?
+-----------+------+----------------------+------+---------+------+--------+------------+
¦ table ¦ type ¦ possible_keys ¦ key ¦ key_len ¦ ref ¦ rows ¦ Extra ¦
+-----------+------+----------------------+------+---------+------+--------+------------+
¦ tablename ¦ ALL ¦ field1,field2,field3 ¦ NULL ¦ NULL ¦ NULL ¦ 104500 ¦ where used ¦
+-----------+------+----------------------+------+---------+------+--------+------------+
1 row in set (0.00 sec)
Is union working on mysql 3.23.58?
Not sure, it should be in the online docs. I'd upgrade, the 3.23 versions are pretty much history.
Also, how should I use an union?
Select count(primary) from table where field1 = 1
union
Select count(primary) from table where field2 = 1
union
Select count(primary) from table where field3 = 1
although thinking about it, it might lead to a different total than your original query.
Unfortunately, this query is still long, between 2-3 secs. Any suggestion?
SELECT COUNT(primary) FROM table WHERE 1 IN(field1,field2,field3);
+-----------+--------+---------------+---------+---------+----------------------+--------+----------------+
¦ table ¦ type ¦ possible_keys ¦ key ¦ key_len ¦ ref ¦ rows ¦ Extra ¦
+-----------+--------+---------------+---------+---------+----------------------+--------+----------------+
¦ table1 ¦ ALL ¦ field1 ¦ NULL ¦ NULL ¦ NULL ¦ 104540 ¦ Using filesort ¦
¦ table2 ¦ eq_ref ¦ PRIMARY ¦ PRIMARY ¦ 4 ¦ table1.field1 ¦ 1 ¦ ¦
¦ table3 ¦ eq_ref ¦ PRIMARY ¦ PRIMARY ¦ 4 ¦ table1.field2 ¦ 1 ¦ ¦
+-----------+--------+---------------+---------+---------+----------------------+--------+----------------+
Is this query optimal? Any comment here?
select count(primary) from from table where field1=1 and field 2=1 and field3=1
union
select count(primary) from from table where field1=1 and field 2=1 and field3=0
...
until you have all 8 combinations of field1,2,3.
With a combined index of all 3 fields, each query is going to be essentially no time, and 8 times almost 0 is still almost 0. Then you just need to add the 8 numbers together.
select my_recordid from my_records where postdateunixtimestamp >= UNIX_TIMESTAMP(date_add(curdate(), interval -5 day));
postdateunixtimestamp is INT(14) and has an index.
Everything is OK and the index is used if I check records for the last 189 days (every number that is <= 189):
explain select my_recordid from my_records where postdateunixtimestamp >= UNIX_TIMESTAMP(date_add(curdate(), interval -189 day));
+------------+-------+-----------------------+-----------------------+---------+------+-------+------------+
¦ table ¦ type ¦ possible_keys ¦ key ¦ key_len ¦ ref ¦ rows ¦ Extra ¦
+------------+-------+-----------------------+-----------------------+---------+------+-------+------------+
¦ my_records ¦ range ¦ postdateunixtimestamp ¦ postdateunixtimestamp ¦ 5 ¦ NULL ¦ 16872 ¦ where used ¦
+------------+-------+-----------------------+-----------------------+---------+------+-------+------------+
1 row in set (0.00 sec)
Now, if I use 190 or a bigger number, the index is not used any more:
explain select my_recordid from my_records where postdateunixtimestamp >= UNIX_TIMESTAMP(date_add(curdate(), interval -190 day));
+------------+------+-----------------------+------+---------+------+-------+------------+
¦ table ¦ type ¦ possible_keys ¦ key ¦ key_len ¦ ref ¦ rows ¦ Extra ¦
+------------+------+-----------------------+------+---------+------+-------+------------+
¦ my_records ¦ ALL ¦ postdateunixtimestamp ¦ NULL ¦ NULL ¦ NULL ¦ 60395 ¦ where used ¦
+------------+------+-----------------------+------+---------+------+-------+------------+
1 row in set (0.00 sec)
Why is that? What am I doing wrong? Why mysql does not use the index if the range is bigger?
Why mysql does not use the index if the range is bigger?
Based on column statistics, if MySQL predicts the number of rows returned by a query will equate to a sizable percentage of the entire table, it will ignore the index. The reasoning is that a table scan will work out cheaper than the cost of utilizing the index.
arran.
define another field (field4) to be the product of
(field1-x), (field2-y), (field3-z)
This will be zero only if field1=x or field2=y or field3=z
and can be indexed. Then you'll just need a simple SELECT blah FROM blah WHERE field4=0
I can't think of any solution that will use an index to do what you are trying to do simply and in 1 query. Interesting, though.