rows missing with group by added - mysql

this is probably something very noob of me
i have the following table
+------------+-------------+------+-----+---------+----------------+
| Field | Type | Null | Key | Default | Extra |
+------------+-------------+------+-----+---------+----------------+
| id | int(11) | NO | PRI | NULL | auto_increment |
| from_id | int(11) | YES | MUL | NULL | |
| to_id | int(11) | YES | MUL | NULL | |
| reply_cost | int(5) | YES | | 0 | |
| date | timestamp | YES | | NULL | |
| body | text | YES | | NULL | |
| read_ | char(1) | YES | | 0 | |
| trash | tinyint(1) | YES | MUL | 0 | |
| trashDate | datetime | YES | | NULL | |
| ip_address | varchar(20) | YES | | NULL | |
+------------+-------------+------+-----+---------+----------------+
a select like
select id,from_id,to_id,date from mail where to_id='100' order by id desc limit 50;
returns
+----------+---------+-------+---------------------+
| id | from_id | to_id | date |
+----------+---------+-------+---------------------+
| 30071061 | 142 | 100 | 2013-08-15 04:39:56 |
| 30070785 | 282 | 100 | 2013-08-15 02:29:00 |
| 30064666 | 282 | 100 | 2013-08-14 16:10:39 |
| 30042809 | 458582 | 100 | 2013-08-12 15:50:45 |
| 30042560 | 458582 | 100 | 2013-08-12 15:28:39 |
| 30042557 | 458582 | 100 | 2013-08-12 15:28:22 |
| 30022845 | 458582 | 100 | 2013-08-10 17:32:40 |
| 30022834 | 458582 | 100 | 2013-08-10 17:31:22 |
| 30018276 | 458582 | 100 | 2013-08-10 06:09:27 |
| 30018275 | 458582 | 100 | 2013-08-10 06:09:00 |
but a select like this
select id,from_id,to_id,date from mail where to_id='100' group by from_id order by id desc limit 50;
outputs like this (from_id 282 is missing)
+----------+---------+-------+---------------------+
| id | from_id | to_id | date |
+----------+---------+-------+---------------------+
| 30017678 | 142 | 100 | 2013-08-10 01:56:38 |
| 29928935 | 189638 | 100 | 2013-07-31 18:33:01 |
| 29894382 | 458582 | 100 | 2013-07-27 22:15:53 |
| 29883054 | 409699 | 100 | 2013-07-26 15:22:35 |
any idea how this can be avoided ?
EDIT: forgot to mention, the goal is to return only one row per from_id.

What about the query
select id,from_id,to_id,date from mail where to_id='100' order by id, from_id desc limit 50;
That should work, hopefully.

Related

Optimize SELECT COUNT(DISTINCT(col)) var, col2 var2 FROM table WHERE col<>'X' and col2 between 'Y' and 'Z' GROUP BY var2 ORDER BY var DESC; for speed?

I have this query and it takes ages (about 10 min) to complete.
SELECT COUNT(DISTINCT(column)) var,
column2 var2
FROM table
WHERE column<>'X' and
column2 between 'Y' and 'Z'
GROUP BY var2
ORDER BY var DESC
Any ideas how to optimize for speed? I tried with indexes but still slow. Maybe they are not set properly. Y and Z are timestamps, if it matters, and X is something that is not needed at all for this query but is in the table for it is needed for other queries from the same app. The table is very large - millions of rows, and it is yet to grow.
Edit: Here is the EXPLAIN result from an example:
mysql> EXPLAIN SELECT COUNT(DISTINCT(ip)) v, geo n from idevaff_iptracking where geo<>'XX' and stamp between '1525122000' and '1543615199' group by n order by v desc;
+------+-------------+--------------------+-------+------------------------+--------------+---------+------+---------+-----------------------------------------------------------+
| id | select_type | table | type | possible_keys | key | key_len | ref | rows | Extra |
+------+-------------+--------------------+-------+------------------------+--------------+---------+------+---------+-----------------------------------------------------------+
| 1 | SIMPLE | idevaff_iptracking | range | stamp,geo,geo_stamp_ip | geo_stamp_ip | 9 | NULL | 3469323 | Using where; Using index; Using temporary; Using filesort |
+------+-------------+--------------------+-------+------------------------+--------------+---------+------+---------+-----------------------------------------------------------+
1 row in set (0.00 sec)
Table locums are as follows:
id,acct_id,ip,refer,stamp,hit_time,hit_date,src1,src2,split,sub_id,tid1,tid2,tid3,tid4,target_url,geo.
Indexes are as follows:
mysql> SHOW INDEX FROM idevaff_iptracking
-> ;
+--------------------+------------+--------------------+--------------+-------------+-----------+-------------+----------+--------+------+------------+---------+---------------+
| Table | Non_unique | Key_name | Seq_in_index | Column_name | Collation | Cardinality | Sub_part | Packed | Null | Index_type | Comment | Index_comment |
+--------------------+------------+--------------------+--------------+-------------+-----------+-------------+----------+--------+------+------------+---------+---------------+
| idevaff_iptracking | 0 | PRIMARY | 1 | id | A | 6775984 | NULL | NULL | | BTREE | | |
| idevaff_iptracking | 1 | acct_id_ip | 1 | acct_id | A | 2 | NULL | NULL | | BTREE | | |
| idevaff_iptracking | 1 | acct_id_ip | 2 | ip | A | 6775984 | NULL | NULL | YES | BTREE | | |
| idevaff_iptracking | 1 | ip | 1 | ip | A | 6775984 | NULL | NULL | YES | BTREE | | |
| idevaff_iptracking | 1 | stamp | 1 | stamp | A | 6775984 | NULL | NULL | | BTREE | | |
| idevaff_iptracking | 1 | acct_id | 1 | acct_id | A | 4 | NULL | NULL | | BTREE | | |
| idevaff_iptracking | 1 | geo | 1 | geo | A | 440 | NULL | NULL | YES | BTREE | | |
| idevaff_iptracking | 1 | tid1 | 1 | tid1 | A | 276 | NULL | NULL | YES | BTREE | | |
| idevaff_iptracking | 1 | tid2 | 1 | tid2 | A | 514 | NULL | NULL | YES | BTREE | | |
| idevaff_iptracking | 1 | tid3 | 1 | tid3 | A | 34 | NULL | NULL | YES | BTREE | | |
| idevaff_iptracking | 1 | tid4 | 1 | tid4 | A | 5623 | NULL | NULL | YES | BTREE | | |
| idevaff_iptracking | 1 | acct_id_stamp_ip | 1 | acct_id | A | 744 | NULL | NULL | | BTREE | | |
| idevaff_iptracking | 1 | acct_id_stamp_ip | 2 | stamp | A | 6775984 | NULL | NULL | | BTREE | | |
| idevaff_iptracking | 1 | acct_id_stamp_ip | 3 | ip | A | 6775984 | NULL | NULL | YES | BTREE | | |
| idevaff_iptracking | 1 | geo_stamp_ip | 1 | geo | A | 22362 | NULL | NULL | YES | BTREE | | |
| idevaff_iptracking | 1 | geo_stamp_ip | 2 | stamp | A | 6775984 | NULL | NULL | | BTREE | | |
| idevaff_iptracking | 1 | geo_stamp_ip | 3 | ip | A | 6775984 | NULL | NULL | YES | BTREE | | |
| idevaff_iptracking | 1 | acct_id_tid1_stamp | 1 | acct_id | A | 658 | NULL | NULL | | BTREE | | |
| idevaff_iptracking | 1 | acct_id_tid1_stamp | 2 | tid1 | A | 11866 | NULL | NULL | YES | BTREE | | |
| idevaff_iptracking | 1 | acct_id_tid1_stamp | 3 | stamp | A | 6775984 | NULL | NULL | | BTREE | | |
| idevaff_iptracking | 1 | acct_id_tid2_stamp | 1 | acct_id | A | 2 | NULL | NULL | | BTREE | | |
| idevaff_iptracking | 1 | acct_id_tid2_stamp | 2 | tid2 | A | 18666 | NULL | NULL | YES | BTREE | | |
| idevaff_iptracking | 1 | acct_id_tid2_stamp | 3 | stamp | A | 6775984 | NULL | NULL | | BTREE | | |
| idevaff_iptracking | 1 | acct_id_tid3_stamp | 1 | acct_id | A | 2 | NULL | NULL | | BTREE | | |
| idevaff_iptracking | 1 | acct_id_tid3_stamp | 2 | tid3 | A | 1832 | NULL | NULL | YES | BTREE | | |
| idevaff_iptracking | 1 | acct_id_tid3_stamp | 3 | stamp | A | 6775984 | NULL | NULL | | BTREE | | |
| idevaff_iptracking | 1 | acct_id_tid4_stamp | 1 | acct_id | A | 2 | NULL | NULL | | BTREE | | |
| idevaff_iptracking | 1 | acct_id_tid4_stamp | 2 | tid4 | A | 5060 | NULL | NULL | YES | BTREE | | |
| idevaff_iptracking | 1 | acct_id_tid4_stamp | 3 | stamp | A | 6775984 | NULL | NULL | | BTREE | | |
+--------------------+------------+--------------------+--------------+-------------+-----------+-------------+----------+--------+------+------------+---------+---------------+
29 rows in set (0.00 sec)
Add this composite index:
INDEX(column2, column)
If that does not suffice, we need to see SHOW CREATE TABLE in order to discuss further. (geo_stamp_ip is not as good.)
It is usually a mistake to splay an array (the tid's) across columns.
EXPLAIN FORMAT=JSON
SELECT COUNT(DISTINCT ip) v, geo n
from idevaff_iptracking
where geo<>'XX'
and stamp between '1525122000' AND '1543615199'
group by n
order by v desc;
Some of the indexes are redundant. In general, INDEX(a) can be removed if you have INDEX(a,b). (For example: acct_id_ip)

Needed aid with complicated MySQL query - very narrow scope

Here are my TABLES described and their contents:
users:
+-----------------+--------------+------+-----+---------+----------------+
| Field | Type | Null | Key | Default | Extra |
+-----------------+--------------+------+-----+---------+----------------+
| id | int(11) | NO | PRI | NULL | auto_increment |
| public_key_path | varchar(100) | NO | | NULL | |
| email | varchar(50) | NO | | NULL | |
| pbox | varchar(50) | YES | UNI | NULL | |
+-----------------+--------------+------+-----+---------+----------------+
contents:
+----+-------------------+----------------------+--------+
| id | public_key_path | email | pbox |
+----+-------------------+----------------------+--------+
| 33 | /path/to/pubkey1/ | FirstUser#email.com | Pbox01 |
| 34 | /path/to/pubkey2/ | SecondUser#email.com | Pbox02 |
| 35 | /path/to/pubkey3/ | ThirdUser#email.com | Pbox03 |
+----+-------------------+----------------------+--------+
files:
+-----------+--------------+------+-----+---------+----------------+
| Field | Type | Null | Key | Default | Extra |
+-----------+--------------+------+-----+---------+----------------+
| id | int(11) | NO | PRI | NULL | auto_increment |
| file_path | varchar(100) | NO | UNI | NULL | |
| owner_id | int(11) | NO | MUL | NULL | |
+-----------+--------------+------+-----+---------+----------------+
contents:
+-----+-----------------+----------+
| id | file_path | owner_id |
+-----+-----------------+----------+
| 104 | /path/to/file1/ | 33 |
| 105 | /path/to/file2/ | 34 |
| 106 | /path/to/file3/ | 35 |
| 107 | /path/to/file4/ | 33 |
| 108 | /path/to/file5/ | 33 |
| 109 | /path/to/file6/ | 34 |
+-----+-----------------+----------+
encrypted_symmetric_keys:
+----------+--------------+------+-----+---------+----------------+
| Field | Type | Null | Key | Default | Extra |
+----------+--------------+------+-----+---------+----------------+
| id | int(11) | NO | PRI | NULL | auto_increment |
| key_path | varchar(100) | YES | UNI | NULL | |
| file_id | int(11) | NO | MUL | NULL | |
| user_id | int(11) | NO | MUL | NULL | |
+----------+--------------+------+-----+---------+----------------+
contents:
+-----+---------------------+---------+---------+
| id | key_path | file_id | user_id |
+-----+---------------------+---------+---------+
| 106 | /path/to/key1forU1/ | 104 | 33 |
| 107 | /path/to/key2forU2/ | 105 | 34 |
| 108 | /path/to/key3forU3/ | 106 | 35 |
| 109 | /path/to/key4forU1/ | 107 | 33 |
| 110 | /path/to/key5forU1/ | 108 | 33 |
| 111 | /path/to/key6forU2/ | 109 | 34 |
| 112 | /path/to/key3forU1/ | 106 | 33 |
| 113 | /path/to/key2forU1/ | 105 | 33 |
| 114 | /path/to/key6forU1/ | 109 | 33 |
+-----+---------------------+---------+---------+
This is a newbie database for a server that stores filepaths that are encrypted with encrypted symmetric keys(ESKs).
If there is key_path /path/to/key1forU1/ that means that the key is stored for file1 for user1.
I need a query that, when given file_path (ex. "/path/to/file1/") lists all users that have access to this file.
Let me know if you need any more information, I'll provide it immediately.
I know that this is a very localized question, but I've been thinking for more than an hour about that now and I'm having horrible problems with wrapping my head around it.
Thank you very much in advance.
EDIT:
My final set of data I need is, when given
'/path/to/file1/'
would return
FirstUser#email.com
But when given for example
/path/to/file2/'
would return
FirstUser#email.com
SecondUser#email.com
because
I think this is what you are looking for
as this will give you all email that are using file_path = '/path/to/file6/' except the owner's email
SELECT su.email
FROM encrypted_symmetric_keys AS c
INNER JOIN users AS su ON su.id = c.user_id
INNER JOIN files AS f ON f.id = c.file_id AND f.owner_id <> c.user_id
WHERE f.file_path = '/path/to/file6/'

How To select Query

I have a table view named as tes.
+--------------+--------------+------+-----+---------+-------+
| Field | Type | Null | Key | Default | Extra |
+--------------+--------------+------+-----+---------+-------+
| id_oba | int(11) | NO | | NULL | |
| nama_obat | varchar(120) | NO | | NULL | |
| satuan | varchar(20) | YES | | NULL | |
| stok_awal | int(5) | YES | | NULL | |
| persediaan | int(5) | YES | | NULL | |
| nama_suplier | varchar(30) | NO | | NULL | |
| pemakaian | int(4) | NO | | NULL | |
| tanggal | date | YES | | NULL | |
+--------------+--------------+------+-----+---------+-------+
When I execute:
select id_oba, nama_obat, satuan, stok_awal, sum(pemakaian) AS pemakaian, persediaan,
from tes group by id_oba;
I get this result:
+--------+-----------+--------+-----------+-----------+------------+
| id_oba | nama_obat | satuan | stok_awal | pemakaian | persediaan |
+--------+-----------+--------+-----------+-----------+------------+
| 1 | Paramex | Botol | 30 | 40 | 5 |
| 2 | Oskadon | Botol | 30 | 41 | 27 |
| 3 | Lindon | Botol | 31 | 30 | 4 |
+--------+-----------+--------+-----------+-----------+------------+
How can I modify my query to get the result like this?
+--------+-----------+--------+-----------+-----------+------------+-------+
| id_oba | nama_obat | satuan | stok_awal | pemakaian | persediaan | total |
+--------+-----------+--------+-----------+-----------+------------+-------+
| 1 | Paramex | Botol | 30 | 40 | 5 | 45 |
| 2 | Oskadon | Botol | 30 | 41 | 27 | 67 |
| 3 | Lindon | Botol | 31 | 30 | 4 | 34 |
+--------+-----------+--------+-----------+-----------+------------+-------+
Please help me with my problem.
Thanks.
Change like this
select id_oba, nama_obat, satuan, stok_awal, sum(pemakaian) AS pemakaian,
persediaan,(sum(pemakaian)+persediaan) as total from tes group by id_oba;

Mysql sum of every 5 data

Hello I have table named eod where i tons of data by date. here is the schema of the table:
+------------+-------------+------+-----+---------+----------------+
| Field | Type | Null | Key | Default | Extra |
+------------+-------------+------+-----+---------+----------------+
| ID | int(11) | NO | PRI | NULL | auto_increment |
| ticker | varchar(20) | NO | MUL | NULL | |
| entry_date | date | NO | MUL | NULL | |
| high | float(10,2) | NO | MUL | NULL | |
| low | float(10,2) | NO | MUL | NULL | |
| close | float(10,2) | NO | MUL | NULL | |
| vol | int(11) | NO | MUL | NULL | |
+------------+-------------+------+-----+---------+----------------+
here are few sample of data:
+----+-----------+------------+------+------+-------+--------+
| ID | ticker | entry_date | high | low | close | vol |
+----+-----------+------------+------+------+-------+--------+
| 1 | x | 2013-02-20 | 6.70 | 6.50 | 6.50 | 136500 |
| 2 | y | 2013-02-24 | 6.60 | 6.40 | 6.40 | 174500 |
| 3 | z | 2013-02-25 | 6.60 | 6.40 | 6.40 | 214000 |
| 4 | x | 2013-02-26 | 6.50 | 6.30 | 6.40 | 238000 |
| 5 | x | 2013-02-27 | 6.50 | 6.20 | 6.20 | 279000 |
| 6 | a | 2013-02-28 | 6.20 | 6.00 | 6.00 | 260500 |
| 7 | x | 2013-03-03 | 6.10 | 5.70 | 5.70 | 131000 |
| 8 | a | 2013-03-04 | 6.10 | 5.80 | 6.00 | 150000 |
| 9 | x | 2013-03-05 | 6.20 | 6.00 | 6.00 | 95000 |
| 10 | z | 2013-03-06 | 6.10 | 6.00 | 6.00 | 84000 |
+----+-----------+------------+------+------+-------+--------+
I want to know how to get sum of every 5 vol, means from ID 1 to 5, then 6 to 10 .....continues by ticker.
sorry for creating confusion at the first time.
Try this:
SELECT sum(column), floor((id-1)/5) + 1 as min_id
FROM table_name
GROUP BY min_id
Try this
SELECT SUM(vol)
FROM (
SELECT vol, TRUNCATE(id/5,0) AS id
FROM eod) AS t
GROUP BY id
Not tested but logic is correct

adding an additional item in SQL statement causes slow performance

I have a sql statement that looks like this:
SELECT colID
FROM tableName
WHERE ColDateStart <='$lowerDate'
AND ColDateStart>='$upperDate'
AND ColVcamID='$id1'
AND ColVlviID='$id2'
AND ColSomeID='$id3';
All the columns in the WHERE statment are indexed columns.
When I run this it takes over a second. However when I run this without other Id3, the performance is considerably improved (0.03 seconds).
When I run explain, with otherId3, it uses an index merge using otherId1 and otherId3. However when I remove the otherId3, it uses the single index of otherId2.
Why does adding otherId3 make an impact on the performance?
Table Structure:
+----------------------+-------------+------+-----+---------------------+----------------+
| Field | Type | Null | Key | Default | Extra |
+----------------------+-------------+------+-----+---------------------+----------------+
| ColID | int(11) | NO | PRI | NULL | auto_increment |
| ColCustID | int(11) | NO | MUL | 0 | |
| ColCarrID | int(11) | NO | MUL | NULL | |
| ColTariID | int(11) | NO | MUL | 0 | |
| ColCarrierRef | varchar(30) | NO | MUL | | |
| ColNumbID | int(11) | NO | MUL | 0 | |
| ColVlviID | int(11) | NO | MUL | NULL | |
| ColVcamID | int(11) | NO | MUL | NULL | |
| ColSomeID | int(11) | NO | MUL | NULL | |
| ColVlnsID | int(11) | NO | MUL | NULL | |
| ColNGNumber | varchar(12) | NO | | | |
| ColOrigNumber | varchar(16) | NO | MUL | NULL | |
| ColCLIRestrictedFlag | int(2) | NO | | NULL | |
| ColOrigLocality | varchar(11) | NO | MUL | | |
| ColOrigAreaCode | varchar(11) | NO | MUL | | |
| ColTermNumber | varchar(16) | NO | MUL | NULL | |
| ColBatchNumber | varchar(10) | NO | | | |
| ColDateStart | date | NO | MUL | 0000-00-00 | |
| ColDateClear | date | NO | | 0000-00-00 | |
| ColTimeStart | time | NO | | 00:00:00 | |
| ColTimeClear | time | NO | | 00:00:00 | |
| ColCallLength | time | NO | | 00:00:00 | |
| ColRingLength | time | NO | | 00:00:00 | |
| ColEffectiveFlag | smallint(1) | NO | MUL | NULL | |
| ColUnansweredFlag | smallint(1) | NO | MUL | NULL | |
| ColEngagedFlag | smallint(1) | NO | | NULL | |
| ColRecID | int(11) | NO | MUL | NULL | |
| ColCreatedUserID | int(11) | NO | | 0 | |
| ColCreatedDatetime | datetime | NO | MUL | 0000-00-00 00:00:00 | |
| ColDirection | int(1) | NO | MUL | NULL | |
+----------------------+-------------+------+-----+---------------------+----------------+
Indexes
+-------+------------+-------------------------------+--------------+---------------------+-----------+-------------+----------+--------+------+------------+---------+
| Table | Non_unique | Key_name | Seq_in_index | Column_name | Collation | Cardinality | Sub_part | Packed | Null | Index_type | Comment |
+-------+------------+-------------------------------+--------------+---------------------+-----------+-------------+----------+--------+------+------------+---------+
| tableName | 0 | PRIMARY | 1 | ColID | A | 18031283 | NULL | NULL | | BTREE | |
| tableName | 1 | idx_ColCustID | 1 | ColCustID | A | 1339 | NULL | NULL | | BTREE | |
| tableName | 1 | idx_ColNumbID | 1 | ColNumbID | A | 24366 | NULL | NULL | | BTREE | |
| tableName | 1 | idx_colOrigNumber | 1 | colOrigNumber | A | 4507820 | NULL | NULL | | BTREE | |
| tableName | 1 | idx_colOrigLocality | 1 | colOrigLocality | A | 36873 | NULL | NULL | | BTREE | |
| tableName | 1 | idx_colOrigAreaCode | 1 | colOrigAreaCode | A | 696 | NULL | NULL | | BTREE | |
| tableName | 1 | idx_colTermNumber | 1 | colTermNumber | A | 137643 | NULL | NULL | | BTREE | |
| tableName | 1 | idx_colDateStart | 1 | colDateStart | A | 3639 | NULL | NULL | | BTREE | |
| tableName | 1 | idx_colEffectiveFlag | 1 | colEffectiveFlag | A | 2 | NULL | NULL | | BTREE | |
| tableName | 1 | idx_colUnansweredFlag | 1 | colUnansweredFlag | A | 2 | NULL | NULL | | BTREE | |
| tableName | 1 | idx_colEngagedFlag | 1 | colUnansweredFlag | A | 2 | NULL | NULL | | BTREE | |
| tableName | 1 | idx_colTariID | 1 | colTariID | A | 91 | NULL | NULL | | BTREE | |
| tableName | 1 | idx_CustID_DateStart | 1 | colCustID | A | 1339 | NULL | NULL | | BTREE | |
| tableName | 1 | idx_CustID_DateStart | 2 | colDateStart | A | 693510 | NULL | NULL | | BTREE | |
| tableName | 1 | idx_NumbID_DateStart | 1 | colNumbID | A | 24366 | NULL | NULL | | BTREE | |
| tableName | 1 | idx_NumbID_DateStart | 2 | colDateStart | A | 4507820 | NULL | NULL | | BTREE | |
| tableName | 1 | idx_colRecID | 1 | colRecID | A | 214658 | NULL | NULL | | BTREE | |
| tableName | 1 | idx_colCarrierRef | 1 | colCarrierRef | A | 6010427 | NULL | NULL | | BTREE | |
| tableName | 1 | idx_colCustID_colTermNumber | 1 | colCustID | A | 1339 | NULL | NULL | | BTREE | |
| tableName | 1 | idx_colCustID_colTermNumber | 2 | colTermNumber | A | 143105 | NULL | NULL | | BTREE | |
| tableName | 1 | idx_colCreatedDatetime | 1 | colCreatedDatetime | A | 474507 | NULL | NULL | | BTREE | |
| tableName | 1 | idx_colDirection | 1 | colDirection | A | 2 | NULL | NULL | | BTREE | |
| tableName | 1 | idx_colVlviID | 1 | colVlviID | A | 4133 | NULL | NULL | | BTREE | |
| tableName | 1 | idx_colSomeID | 1 | colSomeID | A | 10 | NULL | NULL | | BTREE | |
| tableName | 1 | idx_colVcamID | 1 | colVcamID | A | 7 | NULL | NULL | | BTREE | |
| tableName | 1 | idx_colVlnsID | 1 | colVlnsID | A | 18 | NULL | NULL | | BTREE | |
| tableName | 1 | idx_colCarrID | 1 | colCarrID | A | 4 | NULL | NULL | | BTREE | |
+-------+------------+-------------------------------+--------------+---------------------+-----------+-------------+----------+--------+------+------------+---------+
First up, you have far too may indexes. Most of those indexes are likely pointless. If you aren't using a specific index for WHERE criteria, JOINs, or ORDERing, then remove it as it just slows things down.
Next up, for your query you specify 3 columns that are always in the query comprising 1x DATE and 2x INT columns. The DATE column should be first as a date range is pretty fast on an index, and then the two INTs. This gives a starting point of the following 3-column index
CREATE INDEX searchIndex
ON tableName (ColDateStart,ColVlviID,ColVcamID)
USING BTREE;
More information on that available here : http://dev.mysql.com/doc/refman/5.0/en/multiple-column-indexes.html
I ordered the columns that way intentionally. ColDateStart for the date range filtering, followed by the other columns in decreasing order of cardinality. I selected ColVlviID as a second column as it has a cardinality of 4133 compared to ColVcamID having a cardinality of 7. This will allow MySQL to more efficiently reduce the matching rows.
Now, assuming colSomeID is the last column, I might instead do the following
CREATE INDEX searchIndex_someID
ON tableName (ColDateStart,ColVlviID,ColVcamID,ColSomeID)
USING BTREE;
This 3-column index will help MySQL get down to the applicable dataset before checking for that last ID. Optioanlly you could add a 4th column to that index at the end, if you are commonly filtering in another particular INT column.
As an aside, you may want to consider the following instead of the dateCol criteria
SELECT colID
FROM tableName
WHERE ColDateStart BETWEEN DATE('$lowerDate') AND DATE('$upperDate')
AND ColVcamID=$id1
AND ColVlviID=$id2
AND ColSomeID=$id3
The above all of course assumes that you are sanitising the variables before executing the query. I have removed the quotes from the $idx variables, as they should be numeric and therefore do not need to be entered as strings.
SELECT id
FROM tableName FORCE INDEX(`idx_otherId2`)
WHERE dateCol <='$lowerDate'
AND dateCol>='$upperDate'
AND otherId1='$id1'
AND otherId2='$id2'
AND otherId3='$id3';