Once again, Geir Høydalsvik and I had the pleasure of hosting a MySQL mini-seminar in Trondheim. 25+ attendants from at least 7 different companies and a few professors from the computer science dept. at NTNU showed up on yesterdays event. I recognized many of these from the first seminar but there were some new faces as well.
This time, Mark Leith came on a visit from the UK. He gave an introduction to Performance Schema and ps_helper. ps_helper is a really nice tool to make sense of the overwhelming amount of data collected by PS. He also gave a very convincing demo of MySQL Enterprise Monitor (MEM). More than a few attendants now plan to give MEM a try in their environment. You can too - there's a 30 day trial, which should be more than enough to decide if you need it :-)
Like last time, we had great discussions, pizza and a very good time. I'm looking forward to the next seminar already.
If you're interested, Mark's PS presentation can be found on slideshare. ps_helper is both on github and on his blog. ps_helper comes highly recommended!
Showing posts with label mysql. Show all posts
Showing posts with label mysql. Show all posts
Friday, October 18, 2013
Wednesday, February 13, 2013
DBT-3 Q3: 6 x performance in MySQL 5.6.10
When MySQL gets a query, it is the job of the optimizer to find the cheapest way to execute that query. Decisions include access method (range access, table scan, index lookup etc), join order, sorting strategy etc. If we simplify a bit, the optimizer first identifies the different ways to access each table and calculate their cost. After that, the join order is decided.
However, some access methods can only be considered after the join order has been decided and therefore gets special treatment in the MySQL optimizer. For join conditions, e.g. "WHERE table1.col1 = table2.col2", index lookup can only be used in table2 if table1 is earlier in the join sequence. Another class of access methods is only meaningful for tables that are first in the join order. An example is queries with ORDER BY ... LIMIT. Prior to MySQL 5.6.10 there was a bug in MySQL that made the optimizer choose inefficient execution plans for this query type. That's the topic I discuss below.
However, some access methods can only be considered after the join order has been decided and therefore gets special treatment in the MySQL optimizer. For join conditions, e.g. "WHERE table1.col1 = table2.col2", index lookup can only be used in table2 if table1 is earlier in the join sequence. Another class of access methods is only meaningful for tables that are first in the join order. An example is queries with ORDER BY ... LIMIT. Prior to MySQL 5.6.10 there was a bug in MySQL that made the optimizer choose inefficient execution plans for this query type. That's the topic I discuss below.
Tuesday, October 2, 2012
Index merge annoyances fixed in MySQL 5.6
While the index merge access types certainly are useful for a number of queries, there has been some frustration expressed both from customers and the community about how it...
The good news is that we have fixed all these issues in the latest released MySQL 5.6 server.
Consider the problem in BUG#65274 (simplified a bit):
CREATE TABLE phpbb_posts (
...
KEY `topic_id` (`topic_id`),
KEY `forum_id` (`forum_id`)
KEY `tid_fid` (`topic_id`,`forum_id`),
);
SELECT count(*) FROM phpbb_posts WHERE topic_id = 110126 AND forum_id = 19;
- is not used when it should have been
- is used when ref access is obviously better
- merges suboptimal indexes
- is too restricted in which conditions can be used
The good news is that we have fixed all these issues in the latest released MySQL 5.6 server.
Consider the problem in BUG#65274 (simplified a bit):
CREATE TABLE phpbb_posts (
...
KEY `topic_id` (`topic_id`),
KEY `forum_id` (`forum_id`)
KEY `tid_fid` (`topic_id`,`forum_id`),
);
SELECT count(*) FROM phpbb_posts WHERE topic_id = 110126 AND forum_id = 19;
Friday, April 13, 2012
New MySQL optimizer team page launched
FYI: A MySQL Optimizer Team blog aggregate page has been launched. It will be continuously updated with the latest blogs published by the MySQL optimizer developers. Now you can easily stay updated ;-)
Tuesday, October 4, 2011
Optimizer tracing: Query Execution Plan descriptions beyond EXPLAIN
Understanding why MySQL chooses a particular join order or why table scan is chosen instead of range scan is often very hard even for experienced MySQL users. Two almost identical queries, differing only in constant values, may produce completely different plans. That's why we're introducing a great new feature in 5.6: Optimizer Tracing. The target users of this feature are developers and MySQL users experienced enough to understand the ins and outs of EXPLAIN.
What Optimizer Tracing is
You may already have guessed this, but optimizer tracing is a printout of important decisions the MySQL optimizer has done during the process of making the Query Execution Plan.
The trace is presented in JSON format which is easy to read both for humans and others.
Currently, the optimizer trace includes short explanations for:
What Optimizer Tracing is NOT
The feature is not, and never will be, complete in the sense that it does not describe all choices the optimizer does. However, we're going to add more information when we find valuable things to add. We will not guarantee backwards compatibility like we do for EXPLAIN. This gives us the freedom to improve tracing at a high pace without going through multi-release deprecation warnings etc. In other words: optimizer tracing is not a replacement for EXPLAIN.
A quick tour
The best way get a feeling of optimizer tracing is to give it a try. Below is a teaser:
What Optimizer Tracing is
You may already have guessed this, but optimizer tracing is a printout of important decisions the MySQL optimizer has done during the process of making the Query Execution Plan.
The trace is presented in JSON format which is easy to read both for humans and others.
Currently, the optimizer trace includes short explanations for:
- Why the join order was chosen.
- Important query transformations like IN to EXISTS.
- The access methods applicable and why one of them was chosen.
- Which conditions are attached to each table (i.e., what hides behind "Using where" in EXPLAIN)
What Optimizer Tracing is NOT
The feature is not, and never will be, complete in the sense that it does not describe all choices the optimizer does. However, we're going to add more information when we find valuable things to add. We will not guarantee backwards compatibility like we do for EXPLAIN. This gives us the freedom to improve tracing at a high pace without going through multi-release deprecation warnings etc. In other words: optimizer tracing is not a replacement for EXPLAIN.
A quick tour
The best way get a feeling of optimizer tracing is to give it a try. Below is a teaser:
Tuesday, September 27, 2011
Tips and tricks: Killer response time for non-overlapping intervals
Assume you have a table where you store non-overlapping intervals using two columns, e.g. IP ranges. IP ranges are simple to represent using integer notation:
And then you find yourself in a situation where you want to know who, if anyone, owns the IP address X. This can be done using the following query:
MySQL can resolve this using a range scan, but will unfortunately only be able to use the ip_start_int <= X part of the condition as a range as explained here. Thus, the query will either be resolved by range scan if fairly few records have ip_start_int <= X or table scan otherwise. That means unreliable response time because it will be much quicker to query low-valued IPs than high valued IPs. I inserted 1M records into the table before running the queries below:
CREATE TABLE ip_owner (
owner_id int NOT NULL,
/* some columns */
/* some columns */
ip_start_int bigint NOT NULL, /* IP address converted to integer */
ip_end_int bigint NOT NULL, /* IP address converted to integer */
PRIMARY KEY (owner_id),
ip_end_int bigint NOT NULL, /* IP address converted to integer */
PRIMARY KEY (owner_id),
INDEX ip_range (ip_start_int, ip_end_int)
) ENGINE=InnoDB;
And then you find yourself in a situation where you want to know who, if anyone, owns the IP address X. This can be done using the following query:
SELECT * FROM ip_owner WHERE ip_start_int <= X AND ip_end_int >= X;
MySQL can resolve this using a range scan, but will unfortunately only be able to use the ip_start_int <= X part of the condition as a range as explained here. Thus, the query will either be resolved by range scan if fairly few records have ip_start_int <= X or table scan otherwise. That means unreliable response time because it will be much quicker to query low-valued IPs than high valued IPs. I inserted 1M records into the table before running the queries below:
Tuesday, August 23, 2011
The MySQL range access method explained
The range access method uses an index to read a subset of rows that form one or multiple continuous index value intervals. The intervals are defined by the query's range predicates, which are comparisons using any of =, <=>, IN(), IS NULL, IS NOT NULL, >, <, >=, <=, BETWEEN, !=, <> or LIKE.
Some examples:
You know that the range access method is used when EXPLAIN shows type=range.
Naturally, there has to be an index on the column used by the range predicate. Since indexes are ordered, MySQL will, for each interval, dive down the index using the interval start value and read it's way through the index leaves until it reaches the interval end value:
Some examples:
SELECT * FROM blog WHERE author_id IN (1, 7, 8, 10)
SELECT * FROM orders WHERE value > 1000
You know that the range access method is used when EXPLAIN shows type=range.
Naturally, there has to be an index on the column used by the range predicate. Since indexes are ordered, MySQL will, for each interval, dive down the index using the interval start value and read it's way through the index leaves until it reaches the interval end value:
Wednesday, August 17, 2011
The meaning of ref=func in MySQL EXPLAIN
When EXPLAIN shows that a table is accessed using the [eq_]ref access type, we're used to look at the ref column to see where MySQL gets the value to look up from. Usually, we see either "const" if the value is provided as a constant in the query or a column name if the value is read from a column in an already read table:
But what if ref shows the value "func"? In this case, the value used as input to [eq_]ref is the output of some function. A few examples:
EXPLAIN
SELECT acc_rec.cust_id, acc_rec.amount, acc_rec.invoicenumber
FROM accounts_receivable as acc_rec
WHERE acc_rec.cust_id=1;
+----+-------------+---------+------+---------+-------+
| id | select_type | table | type | key | ref |
+----+-------------+---------+------+---------+-------+
| 1 | SIMPLE | acc_rec | ref | cust_id | const |
+----+-------------+---------+------+---------+-------+
EXPLAIN
SELECT acc_rec.cust_id, acc_rec.amount, acc_rec.invoicenumber,
customers.firstname, customers.lastname, customers.phone
FROM accounts_receivable AS acc_rec JOIN customers AS cust
ON acc_rec.cust_id = customers.cust_id;
+----+-------------+---------+--------+---------+-----------------+
| id | select_type | table | type | key | ref |
+----+-------------+---------+--------+---------+-----------------+
| 1 | SIMPLE | acc_rec | ALL | NULL | NULL |
| 1 | SIMPLE | cust | eq_ref | PRIMARY | acc_rec.cust_id |
+----+-------------+---------+--------+---------+-----------------+But what if ref shows the value "func"? In this case, the value used as input to [eq_]ref is the output of some function. A few examples:
Subscribe to:
Posts (Atom)