## Only 1 query which returns 10 rows.
## It took about 66 secs
mysql> explain
SELECT al.log_id , al.user_id , al.page_name ,
al.section_name , al.submit_time , al.url ,
alfm1.value as 'source_env' ,
alfm2.value as 'website_id' ,
alfm3.value as 'index_id'
FROM admin_logs al
LEFT OUTER JOIN
(select * from admin_log_field_map where field_id = 3351
) alfm1 ON al.log_id = alfm1.log_id
LEFT OUTER JOIN
(select * from admin_log_field_map where field_id = 911
) alfm2 ON al.log_id = alfm2.log_id
, admin_log_field_map alfm3
WHERE 1=1
AND al.page_name='Index Management'
AND al.log_id=alfm3.log_id
AND alfm3.field_id=891
AND alfm3.value='jewelry'
ORDER BY al.log_id DESC;
+----+-------------+---------------------+--------+--------------------+------------+---------+---------------------+-------+----------------------------------------------+
| id | select_type | table | type | possible_keys | key | key_len | ref | rows | Extra |
+----+-------------+---------------------+--------+--------------------+------------+---------+---------------------+-------+----------------------------------------------+
| 1 | PRIMARY | <derived2> | system | NULL | NULL | NULL | NULL | 0 | const row not found |
| 1 | PRIMARY | al | ref | idx_622,idx_pgname | idx_pgname | 78 | const | 27720 | Using where; Using temporary; Using filesort |
| 1 | PRIMARY | alfm3 | ref | idx_1533,idx_0311 | idx_1533 | 10 | cms.al.log_id,const | 1 | Using where |
| 1 | PRIMARY | <derived3> | ALL | NULL | NULL | NULL | NULL | 35358 | |
| 3 | DERIVED | admin_log_field_map | ref | idx_0311 | idx_0311 | 5 | | 33098 | Using where |
| 2 | DERIVED | admin_log_field_map | ref | idx_0311 | idx_0311 | 5 | | 1 | Using where |
+----+-------------+---------------------+--------+--------------------+------------+---------+---------------------+-------+----------------------------------------------+
6 rows in set (0.20 sec)
mysql>
mysql>
mysql> show create table admin_logs\G
*************************** 1. row ***************************
Table: admin_logs
Create Table: CREATE TABLE `admin_logs` (
`row_mod` datetime DEFAULT NULL,
`row_create` datetime DEFAULT NULL,
`log_id` int(11) DEFAULT NULL,
`user_id` varchar(50) COLLATE latin1_bin DEFAULT NULL,
`page_name` varchar(75) COLLATE latin1_bin DEFAULT NULL,
`section_name` varchar(125) COLLATE latin1_bin DEFAULT NULL,
`submit_time` datetime DEFAULT NULL,
`url` varchar(255) COLLATE latin1_bin DEFAULT NULL,
`source_environment` varchar(255) COLLATE latin1_bin DEFAULT NULL,
`log` longtext COLLATE latin1_bin,
UNIQUE KEY `idx_622` (`log_id`),
KEY `idx_pgname` (`page_name`)
) ENGINE=InnoDB DEFAULT CHARSET=latin1 COLLATE=latin1_bin
1 row in set (0.00 sec)
mysql> \! hostname
fol-piwikdb01.dca.ftd.untd.com
mysql> show create table admin_log_field_map\G
*************************** 1. row ***************************
Table: admin_log_field_map
Create Table: CREATE TABLE `admin_log_field_map` (
`row_mod` datetime DEFAULT NULL,
`row_create` datetime DEFAULT NULL,
`log_id` int(11) DEFAULT NULL,
`field_id` int(11) DEFAULT NULL,
`value` varchar(255) COLLATE latin1_bin DEFAULT NULL,
UNIQUE KEY `idx_1533` (`log_id`,`field_id`),
KEY `idx_0311` (`field_id`)
) ENGINE=InnoDB DEFAULT CHARSET=latin1 COLLATE=latin1_bin
1 row in set (0.00 sec)
how to get better performance using above query?
Mysql – how to improve query performance
MySQLperformancequery-performance
Related Question
- Mysql query not working
- MySQL Optimization – How to Optimize a Simple Query on a Large Table
- Mysql – Need help improving sql query performance
- MySQL – How to Resolve Query Taking Too Long
- Mysql – Slow SELECT examining whole table
- MySQL – Optimizing Slow SELECT MAX() from View with INNER JOIN
- Mysql – INSERT gives Error Code: 1366. Incorrect string value: ‘\xF0\x9F\x98\x80’ for column
Best Answer
First, lets rewrite the query by dropping the ANSI-89 implicit join syntax and removing the derived tables:
I've also move some of the conditions from the
WHERE
clause to the respondingON
clause, so it is more apparent which indexes you need.From the two outer joins it's clear that from table
admin_log_field_map
, you only need the rows with a fixedfield_id
(either 3351 or 911) and then only the columnslog_id
(to do the join) and thevalue
(to be returned in theSELECT
list):So, a good index for these 2 left joins would be
(field_id, log_id, value)
The third (inner) join to
admin_log_field_map
, is different. You only need the rows with a fixedfield_id
(891) and fixedvalue
('jewelry') and thenlog_id
(to do the join). After that, nothing is really needed for theSELECT
list (thevalue
is already known and fixed):So, a good index for these 2 left joins would be
(field_id, value, log_id)
For the
admin_logs
table, you already have an index on(page_name)
so it will probably be used for theWHERE
condition.So, what you can do is add these two indexes: