Beruflich Dokumente
Kultur Dokumente
Before we begin...
What you need to know
How and why we add indexes to tables The benefits of correct field typing Understanding of the ideals of 3NF Basic understanding of SQL JOINs
This presentation
Very quick introduction to EXPLAIN Improve understanding of MySQL and indexing Simplified examples / results
MySQL won't actually execute the query, just analyse it EXPLAIN helps us understand how and when MySQL will use indexes EXPLAIN returns a table of data from which you identify potential improvements Optimise queries in three ways
Fast, compact structure for identifying row locations Keep indexes in memory by trimming the fat:
Can I reduce the characters in that VARCHAR index? Can I use a TINYINT instead of a BIGINT? Can I use an INTEGER to describe a status or flag (rather than a textual description)?
Chop down your result set as quickly as possible MySQL will only use one index per query/table it cannot combine two separate indexes to make a useful one *
conferences
conference_id INTEGER (PK) location_id INTEGER (FK) topic_id INTEGER (FK) date DATE
All the possible indexes which MySQL could have used Based on a series of very quick lookups and calculations
Full table scans are almost always the slowest query Full table scans, while not always bad, are usually an indication that an index is required
MySQL had two indexes to choose from, but discarded reg reg isn't sufficiently unique
The spread of values can also be a factor (e.g when 99% of rows contain the same value)
Index uniqueness is called cardinality There is scope for some performance increase...
key reg_conf_index
rows 204
Note that the other two keys are still available, just not as effective
possible_keys NULL
key NULL
rows 14052
Without the conf index, we're back to square one The order in which fields were defined in a composite index affects whether it is available for use in a query Remember, we defined our index : (registration_status, conference_id)
Potential workaround: EXPLAIN SELECT * FROM attendees WHERE conference_id = 123 AND registration_status >= -1
table attendees possible_keys reg_conf_index key reg_conf_index rows 204
EXPLAIN Example 2
EXPLAIN SELECT * FROM attendees WHERE surname LIKE 'har%';
table attendees possible_keys surname key surname rows 234
EXPLAIN Example 3
EXPLAIN SELECT * FROM conferences WHERE location_id = 2 OR topic_id IN (4,6,1)
table conferences possible_keys location_id, topic_id key NULL rows 5043
Full table scan avoided could also use UNION (ALL) trick
EXPLAIN Example 4
EXPLAIN SELECT * FROM attendees WHERE MD5(conference_id) = MD5(123)
table attendees possible_keys NULL key NULL rows 14052
A more realistic example? EXPLAIN SELECT * FROM conferences WHERE DATE_FORMAT(date,'%a') = 'Sat'
table conferences possible_keys NULL key NULL rows 5043
JOINs
JOINing together large data sets (>= 100,000) is really where EXPLAIN becomes useful Each JOIN in a query gets its own row in EXPLAIN
Make sure each joined table is getting to its result set as quickly as possible The benefits compound if each join requires less effort
Looks like I need an index on attendees.conference_id There are 13 different values for type Another indication of effort, aside from rows scanned Here, ALL is bad we should be aiming for ref Common values are const, ref, and all http://dev.mysql.com/doc/refman/5.0/en/using-explain.html
There are many more extra values which are discussed in the MySQL manual.
Using filesort
Avoid, because: Doesn't use an index Involves a full scan of your result set Employs a generic (i.e. one size fits all) algorithm Uses the filesystem (eeek) Will get slower with more data
Perfectly acceptable provided you get to your result set as quickly as possible, and keep it predictably small Sometimes unavoidable - ORDER BY RAND() ORDER BY operations can use indexes to do the sorting!
MySQL is using an index, but it's sorting the results slowly ALTER TABLE attendees ADD INDEX conf_surname (conference_id, surname); EXPLAIN SELECT * FROM attendees WHERE conference_id = 123 ORDER BY surname
table attendees possible_keys conference_id, conf_surname key conf_surname rows 331 Extra
Using index
Celebrate, because:
MySQL got your results just by consulting the index, Which could well have been sat in memory MySQL didn't need to even look at the table to get you your results Opening a table can be an expensive operation. MySQL can answer the next query more quickly The fastest way for you to get your data?
Particularly useful...
When you're just interested in a single date or an id Or the COUNT(), SUM(), AVG() etc. of a field
Nothing is actually wrong with this query it could just be quicker! ALTER TABLE attendees ADD INDEX conf_age (conference_id, age); EXPLAIN SELECT AVG(age) FROM attendees WHERE conference_id = 123
table attendees possible_keys conference_id, conf_surname key conf_surname rows 331 Extra Using index
Moving forward...
Just because your queries are fast now, doesn't mean that they will stay that way forever Enable MySQL's Slow Query Log --log-slow-queries=/var/lib/mysql/slow-query.log Defaults to logging queries which take more than 10 seconds --long_query_time=1 Use Percona's microslow patch for values < 1 second Find the query in the log, EXPLAIN it, improve it, rinse and repeat
Moving forward...
Use the command line to identify more general problems mysqladmin -u dbuser -p -r -i 10 extended-status Figures are relative, updated every 10 seconds Slow_queries = number of slow queries in last period Select_Scan = full table scans Select_full_join = full scans to complete join operations Created_tmp_disk_tables = filesorts Key_read_requests/Key_write_requests Determine write/read weighting of our application and alter your indexes accordingly
MySQL Resources