10 things you might not know about mysql

75
10 things you might not know about MySQL Jorge Bernal <[email protected] > Version 0.1

Upload: jorge-bernal

Post on 22-Apr-2015

14.365 views

Category:

Technology


1 download

DESCRIPTION

 

TRANSCRIPT

Page 1: 10 things you might not know about MySQL

10 things you might not know about MySQLJorge Bernal <[email protected]>

Version 0.1

Page 2: 10 things you might not know about MySQL

1Query cache

Page 3: 10 things you might not know about MySQL

Beforemysql> SELECT AVG(Population) FROM City_huge;+‐‐‐‐‐‐‐‐‐‐‐‐‐‐‐‐‐+| AVG(Population) |+‐‐‐‐‐‐‐‐‐‐‐‐‐‐‐‐‐+|     354359.9948 | +‐‐‐‐‐‐‐‐‐‐‐‐‐‐‐‐‐+1 row in set (0.58 sec)

mysql> SELECT AVG(Population) FROM City_huge;+‐‐‐‐‐‐‐‐‐‐‐‐‐‐‐‐‐+| AVG(Population) |+‐‐‐‐‐‐‐‐‐‐‐‐‐‐‐‐‐+|     354359.9948 | +‐‐‐‐‐‐‐‐‐‐‐‐‐‐‐‐‐+1 row in set (0.56 sec)

Page 4: 10 things you might not know about MySQL

Aftermysql> SELECT AVG(Population) FROM City_huge;+‐‐‐‐‐‐‐‐‐‐‐‐‐‐‐‐‐+| AVG(Population) |+‐‐‐‐‐‐‐‐‐‐‐‐‐‐‐‐‐+|     354359.9948 | +‐‐‐‐‐‐‐‐‐‐‐‐‐‐‐‐‐+1 row in set (0.56 sec)

mysql> SELECT AVG(Population) FROM City_huge;+‐‐‐‐‐‐‐‐‐‐‐‐‐‐‐‐‐+| AVG(Population) |+‐‐‐‐‐‐‐‐‐‐‐‐‐‐‐‐‐+|     354359.9948 | +‐‐‐‐‐‐‐‐‐‐‐‐‐‐‐‐‐+1 row in set (0.00 sec)

Page 5: 10 things you might not know about MySQL

The magicSET global query_cache_size=8 * 1024 * 1024;mysql> SHOW GLOBAL VARIABLES LIKE 'query_cache%';+‐‐‐‐‐‐‐‐‐‐‐‐‐‐‐‐‐‐‐‐‐‐‐‐‐‐‐‐‐‐+‐‐‐‐‐‐‐‐‐+| Variable_name                | Value   |+‐‐‐‐‐‐‐‐‐‐‐‐‐‐‐‐‐‐‐‐‐‐‐‐‐‐‐‐‐‐+‐‐‐‐‐‐‐‐‐+| query_cache_limit            | 1048576 | | query_cache_min_res_unit     | 4096    | | query_cache_size             | 8388608 | | query_cache_type             | ON      | | query_cache_wlock_invalidate | OFF     | +‐‐‐‐‐‐‐‐‐‐‐‐‐‐‐‐‐‐‐‐‐‐‐‐‐‐‐‐‐‐+‐‐‐‐‐‐‐‐‐+5 rows in set (0.00 sec)

mysql> SHOW GLOBAL STATUS LIKE 'Qc%';+‐‐‐‐‐‐‐‐‐‐‐‐‐‐‐‐‐‐‐‐‐‐‐‐‐+‐‐‐‐‐‐‐‐‐+| Variable_name           | Value   |+‐‐‐‐‐‐‐‐‐‐‐‐‐‐‐‐‐‐‐‐‐‐‐‐‐+‐‐‐‐‐‐‐‐‐+| Qcache_free_blocks      | 1       | | Qcache_free_memory      | 8378312 | | Qcache_hits             | 1       | | Qcache_inserts          | 1       | | Qcache_lowmem_prunes    | 0       | | Qcache_not_cached       | 0       | | Qcache_queries_in_cache | 1       | | Qcache_total_blocks     | 4       | +‐‐‐‐‐‐‐‐‐‐‐‐‐‐‐‐‐‐‐‐‐‐‐‐‐+‐‐‐‐‐‐‐‐‐+8 rows in set (0.00 sec)

Page 6: 10 things you might not know about MySQL

2Life beyond MyISAM/

InnoDB

Page 7: 10 things you might not know about MySQL

Archivemysql> SELECT ENGINE, (INDEX_LENGTH+DATA_LENGTH) AS Size FROM INFORMATION_SCHEMA.TABLES WHERE TABLE_NAME = 'City_huge';+‐‐‐‐‐‐‐‐+‐‐‐‐‐‐‐‐‐‐+| ENGINE | Size     |+‐‐‐‐‐‐‐‐+‐‐‐‐‐‐‐‐‐‐+| MyISAM | 63203585 | +‐‐‐‐‐‐‐‐+‐‐‐‐‐‐‐‐‐‐+

mysql> SELECT ENGINE, (INDEX_LENGTH+DATA_LENGTH) AS Size FROM INFORMATION_SCHEMA.TABLES WHERE TABLE_NAME = 'City_huge';+‐‐‐‐‐‐‐‐‐+‐‐‐‐‐‐‐‐‐‐+| ENGINE  | Size     |+‐‐‐‐‐‐‐‐‐+‐‐‐‐‐‐‐‐‐‐+| ARCHIVE | 13520399 | +‐‐‐‐‐‐‐‐‐+‐‐‐‐‐‐‐‐‐‐+

Page 8: 10 things you might not know about MySQL

ARCHIVE MyISAM

80% compression

Page 9: 10 things you might not know about MySQL

But...

• Only INSERT and SELECT

• No indexing

Page 10: 10 things you might not know about MySQL

CSVmysql> ALTER TABLE City ENGINE=CSV;Query OK, 0 rows affected (0.05 sec)Records: 0  Duplicates: 0  Warnings: 0

root@warhol:/usr/local/mysql/data/world$ head City.CSV 1,"Kabul","AFG","Kabol",17800002,"Qandahar","AFG","Qandahar",2375003,"Herat","AFG","Herat",1868004,"Mazar‐e‐Sharif","AFG","Balkh",1278005,"Amsterdam","NLD","Noord‐Holland",7312006,"Rotterdam","NLD","Zuid‐Holland",5933217,"Haag","NLD","Zuid‐Holland",4409008,"Utrecht","NLD","Utrecht",2343239,"Eindhoven","NLD","Noord‐Brabant",20184310,"Tilburg","NLD","Noord‐Brabant",193238

Page 11: 10 things you might not know about MySQL

Mergemysql> SHOW CREATE TABLE allweek\G[...]Create Table: CREATE TABLE `allweek` (  `ID` int(11) NOT NULL DEFAULT '0',  `Name` char(35) NOT NULL DEFAULT '',  `CountryCode` char(3) NOT NULL DEFAULT '',  `District` char(20) NOT NULL DEFAULT '',  `Population` int(11) NOT NULL DEFAULT '0',  `modtime` datetime DEFAULT NULL,  KEY `modtime` (`modtime`)) ENGINE=MRG_MyISAM DEFAULT CHARSET=latin1 UNION=(`monday`,`tuesday`,`wednesday`,`thursday`,`citydate`)1 row in set (0.00 sec)

Page 12: 10 things you might not know about MySQL

3AUTO_INCREMENT

woes

Page 13: 10 things you might not know about MySQL

mysql>   CREATE TABLE t (    ‐>    id INT NOT NULL PRIMARY KEY AUTO_INCREMENT    ‐>   );Query OK, 0 rows affected (0.00 sec)

mysql>   INSERT INTO t (id)    ‐>   VALUES (NULL);Query OK, 1 row affected (0.04 sec)

mysql>   SELECT *    ‐>   FROM t    ‐>   WHERE id IS NULL;+‐‐‐‐+| id |+‐‐‐‐+|  1 | +‐‐‐‐+

Page 14: 10 things you might not know about MySQL

But...• id is AUTO_INCREMENT, so it’s 1

• let’s run that again

mysql>   CREATE TABLE t (    ‐>    id INT NOT NULL PRIMARY KEY AUTO_INCREMENT    ‐>   );Query OK, 0 rows affected (0.00 sec)

mysql>   INSERT INTO t (id)    ‐>   VALUES (NULL);Query OK, 1 row affected (0.04 sec)

mysql>   SELECT *    ‐>   FROM t    ‐>   WHERE id IS NULL;+‐‐‐‐+| id |+‐‐‐‐+|  1 | +‐‐‐‐+

Page 15: 10 things you might not know about MySQL

mysql>   CREATE TABLE t (    ‐>    id INT NOT NULL PRIMARY KEY AUTO_INCREMENT    ‐>   );Query OK, 0 rows affected (0.00 sec)

mysql>   INSERT INTO t (id)    ‐>   VALUES (NULL);Query OK, 1 row affected (0.04 sec)

mysql>   SELECT *    ‐>   FROM t    ‐>   WHERE id IS NULL;+‐‐‐‐+| id |+‐‐‐‐+|  1 | +‐‐‐‐+mysql>   SELECT *    ‐>   FROM t    ‐>   WHERE id IS NULL;Empty set (0.00 sec)

mysql> SELECT *   FROM t;+‐‐‐‐+| id |+‐‐‐‐+|  1 | +‐‐‐‐+1 row in set (0.00 sec)

Page 16: 10 things you might not know about MySQL

WTF???

• WHERE ID IS NULL acts as

WHERE ID = LAST_ISERT_ID()

• But only the first time

• Brought to you by some weird ODBC compatibility decision

Page 17: 10 things you might not know about MySQL

4How to get random

data

Page 18: 10 things you might not know about MySQL

SELECT name FROM randomORDER BY RAND()LIMIT 1

Page 19: 10 things you might not know about MySQL

SELECT name FROM randomORDER BY RAND()LIMIT 1X

Wrong!

Page 20: 10 things you might not know about MySQL

There is a better waySELECT nameFROM random JOIN( SELECT CEIL(  RAND() *  (SELECT MAX(id) FROM random))   AS id) AS r2USING (id);

Page 21: 10 things you might not know about MySQL

Really?

Page 22: 10 things you might not know about MySQL

Really?

0,10

1,00

10,00

100,00

1.000,00

10.000,00

100 1000 10000 100000

Seco

nds

Table Size

ORDER BY RAND() Subquery

Page 23: 10 things you might not know about MySQL

So...

Every time you use ORDER BY RAND()...God kills a kitten

Please, think of the kittens

Page 24: 10 things you might not know about MySQL

5Prefix indexes

Page 25: 10 things you might not know about MySQL

There’s no need to index the whole

column

Page 26: 10 things you might not know about MySQL

Name is CHAR(52)mysql> SHOW CREATE TABLE Country\G*************************** 1. row ***************************       Table: CountryCreate Table: CREATE TABLE `Country` (  `Code` char(3) NOT NULL DEFAULT '',  `Name` char(52) NOT NULL DEFAULT '',  `Continent` enum('Asia','Europe','North America','Africa','Oceania','Antarctica','South America') NOT NULL DEFAULT 'Asia',  `Region` char(26) NOT NULL DEFAULT '',  `SurfaceArea` float(10,2) NOT NULL DEFAULT '0.00',  `IndepYear` smallint(6) DEFAULT NULL,  `Population` int(11) NOT NULL DEFAULT '0',  `LifeExpectancy` float(3,1) DEFAULT NULL,  `GNP` float(10,2) DEFAULT NULL,  `GNPOld` float(10,2) DEFAULT NULL,  `LocalName` char(45) NOT NULL DEFAULT '',  `GovernmentForm` char(45) NOT NULL DEFAULT '',  `HeadOfState` char(60) DEFAULT NULL,  `Capital` int(11) DEFAULT NULL,  `Code2` char(2) NOT NULL DEFAULT '',  PRIMARY KEY (`Code`)) ENGINE=MyISAM DEFAULT CHARSET=latin11 row in set (0.02 sec)

Page 27: 10 things you might not know about MySQL

mysql> SELECT COUNT(*) AS Total, COUNT(DISTINCT Name) AS Diff, COUNT(*) ‐ COUNT(DISTINCT Name) AS Dupes FROM Country;+‐‐‐‐‐‐‐+‐‐‐‐‐‐+‐‐‐‐‐‐‐+| Total | Diff | Dupes |+‐‐‐‐‐‐‐+‐‐‐‐‐‐+‐‐‐‐‐‐‐+|   239 |  239 |     0 | +‐‐‐‐‐‐‐+‐‐‐‐‐‐+‐‐‐‐‐‐‐+1 row in set (1.04 sec)mysql> SELECT COUNT(*) AS Total, COUNT(DISTINCT LEFT(Name,50)) AS Diff, COUNT(*) ‐ COUNT(DISTINCT LEFT(Name,50)) AS Dupes FROM Country;+‐‐‐‐‐‐‐+‐‐‐‐‐‐+‐‐‐‐‐‐‐+| Total | Diff | Dupes |+‐‐‐‐‐‐‐+‐‐‐‐‐‐+‐‐‐‐‐‐‐+|   239 |  239 |     0 | +‐‐‐‐‐‐‐+‐‐‐‐‐‐+‐‐‐‐‐‐‐+1 row in set (2.02 sec)

mysql> SELECT COUNT(*) AS Total, COUNT(DISTINCT LEFT(Name,20)) AS Diff, COUNT(*) ‐ COUNT(DISTINCT LEFT(Name,20)) AS Dupes FROM Country;+‐‐‐‐‐‐‐+‐‐‐‐‐‐+‐‐‐‐‐‐‐+| Total | Diff | Dupes |+‐‐‐‐‐‐‐+‐‐‐‐‐‐+‐‐‐‐‐‐‐+|   239 |  239 |     0 | +‐‐‐‐‐‐‐+‐‐‐‐‐‐+‐‐‐‐‐‐‐+1 row in set (0.93 sec)

Page 28: 10 things you might not know about MySQL

mysql> SELECT COUNT(*) AS Total, COUNT(DISTINCT Name) AS Diff, COUNT(*) ‐ COUNT(DISTINCT Name) AS Dupes FROM Country;+‐‐‐‐‐‐‐+‐‐‐‐‐‐+‐‐‐‐‐‐‐+| Total | Diff | Dupes |+‐‐‐‐‐‐‐+‐‐‐‐‐‐+‐‐‐‐‐‐‐+|   239 |  239 |     0 | +‐‐‐‐‐‐‐+‐‐‐‐‐‐+‐‐‐‐‐‐‐+1 row in set (1.04 sec)mysql> SELECT COUNT(*) AS Total, COUNT(DISTINCT LEFT(Name,50)) AS Diff, COUNT(*) ‐ COUNT(DISTINCT LEFT(Name,50)) AS Dupes FROM Country;+‐‐‐‐‐‐‐+‐‐‐‐‐‐+‐‐‐‐‐‐‐+| Total | Diff | Dupes |+‐‐‐‐‐‐‐+‐‐‐‐‐‐+‐‐‐‐‐‐‐+|   239 |  239 |     0 | +‐‐‐‐‐‐‐+‐‐‐‐‐‐+‐‐‐‐‐‐‐+1 row in set (2.02 sec)

mysql> SELECT COUNT(*) AS Total, COUNT(DISTINCT LEFT(Name,20)) AS Diff, COUNT(*) ‐ COUNT(DISTINCT LEFT(Name,20)) AS Dupes FROM Country;+‐‐‐‐‐‐‐+‐‐‐‐‐‐+‐‐‐‐‐‐‐+| Total | Diff | Dupes |+‐‐‐‐‐‐‐+‐‐‐‐‐‐+‐‐‐‐‐‐‐+|   239 |  239 |     0 | +‐‐‐‐‐‐‐+‐‐‐‐‐‐+‐‐‐‐‐‐‐+1 row in set (0.93 sec)

Got it? Cool! Now...

Page 29: 10 things you might not know about MySQL

There is a better wayCREATE DEFINER=`root`@`localhost` PROCEDURE `pref_index`(t_name CHAR(255), c_name CHAR(255))BEGIN

DECLARE plength INT DEFAULT 1;SET @q = CONCAT('SELECT CHARACTER_MAXIMUM_LENGTH INTO @maxlen                                                         FROM INFORMATION_SCHEMA.COLUMNS                                                        WHERE TABLE_SCHEMA = "world2" AND                                                                        TABLE_NAME = "', t_name,'" AND                                                                        COLUMN_NAME = "', c_name, '"');PREPARE q FROM @q;EXECUTE q;DEALLOCATE PREPARE q;

REPEAT        SET @qq = CONCAT('SELECT COUNT(*) ‐ COUNT(DISTINCT ',c_name,')                                                                 into @dupe FROM ',t_name);        SET @pq = CONCAT('SELECT COUNT(*) ‐ COUNT(DISTINCT LEFT(',c_name,',',plength,'))                                                                 into @pdupe FROM ',t_name);

        PREPARE qs FROM @qq;        EXECUTE qs;        DEALLOCATE PREPARE qs;

        PREPARE ps FROM @pq;        EXECUTE ps;        DEALLOCATE PREPARE ps;

        SET plength = plength + 1;UNTIL plength >= @maxlen OR @pdupe = @dupeEND REPEAT;SELECT plength, @pdupe, @dupe;END

Page 30: 10 things you might not know about MySQL

mysql> CALL pref_index('Country', 'Name');+‐‐‐‐‐‐‐‐‐+‐‐‐‐‐‐‐‐+‐‐‐‐‐‐‐+| plength | @pdupe | @dupe |+‐‐‐‐‐‐‐‐‐+‐‐‐‐‐‐‐‐+‐‐‐‐‐‐‐+|      18 |      0 |     0 | +‐‐‐‐‐‐‐‐‐+‐‐‐‐‐‐‐‐+‐‐‐‐‐‐‐+1 row in set (1.18 sec)

Query OK, 0 rows affected (1.18 sec)

mysql> SELECT COUNT(*) AS Total, COUNT(DISTINCT LEFT(Name,18)) AS Diff, COUNT(*) ‐ COUNT(DISTINCT LEFT(Name,18)) AS Dupes FROM Country;+‐‐‐‐‐‐‐+‐‐‐‐‐‐+‐‐‐‐‐‐‐+| Total | Diff | Dupes |+‐‐‐‐‐‐‐+‐‐‐‐‐‐+‐‐‐‐‐‐‐+|   239 |  239 |     0 | +‐‐‐‐‐‐‐+‐‐‐‐‐‐+‐‐‐‐‐‐‐+1 row in set (0.00 sec)

mysql> ALTER TABLE Country ADD KEY (Name(18));Query OK, 239 rows affected (1.48 sec)Records: 239  Duplicates: 0  Warnings: 0

Page 31: 10 things you might not know about MySQL

mysql> CALL pref_index('Country', 'Name');+‐‐‐‐‐‐‐‐‐+‐‐‐‐‐‐‐‐+‐‐‐‐‐‐‐+| plength | @pdupe | @dupe |+‐‐‐‐‐‐‐‐‐+‐‐‐‐‐‐‐‐+‐‐‐‐‐‐‐+|      18 |      0 |     0 | +‐‐‐‐‐‐‐‐‐+‐‐‐‐‐‐‐‐+‐‐‐‐‐‐‐+1 row in set (1.18 sec)

Query OK, 0 rows affected (1.18 sec)

mysql> SELECT COUNT(*) AS Total, COUNT(DISTINCT LEFT(Name,18)) AS Diff, COUNT(*) ‐ COUNT(DISTINCT LEFT(Name,18)) AS Dupes FROM Country;+‐‐‐‐‐‐‐+‐‐‐‐‐‐+‐‐‐‐‐‐‐+| Total | Diff | Dupes |+‐‐‐‐‐‐‐+‐‐‐‐‐‐+‐‐‐‐‐‐‐+|   239 |  239 |     0 | +‐‐‐‐‐‐‐+‐‐‐‐‐‐+‐‐‐‐‐‐‐+1 row in set (0.00 sec)

mysql> ALTER TABLE Country ADD KEY (Name(18));Query OK, 239 rows affected (1.48 sec)Records: 239  Duplicates: 0  Warnings: 0

We just saved 34 bytes per row!

Page 32: 10 things you might not know about MySQL

6InnoDB clustered index

Page 33: 10 things you might not know about MySQL

Primary key

Leaf nodes

Index

Data stored in PK order

Indexes point to PK instead of actual data

Page 34: 10 things you might not know about MySQL

So what?

Page 35: 10 things you might not know about MySQL

Choose your PK wisely

Page 36: 10 things you might not know about MySQL

Load data in ordermysql> load data infile '/tmp/city_order.txt' into table City_huge;Query OK, 818027 rows affected (15.86 sec)Records: 818027  Deleted: 0  Skipped: 0  Warnings: 0

mysql> load data infile '/tmp/city_rand.txt' into table City_huge;Query OK, 818027 rows affected (33 min 23.57 sec)Records: 818027  Deleted: 0  Skipped: 0  Warnings: 0

Page 37: 10 things you might not know about MySQL

7Profiling

Page 38: 10 things you might not know about MySQL

mysql> select * from v_client_portfolio_high;+‐‐‐‐‐‐‐‐‐‐‐+‐‐‐‐‐‐‐‐‐‐‐‐‐‐‐‐‐‐‐+‐‐‐‐‐‐‐‐‐‐‐‐‐‐‐‐‐‐+‐‐‐‐‐‐‐‐‐‐‐‐‐‐‐‐‐+| client_id | client_first_name | client_last_name | portfolio_value |+‐‐‐‐‐‐‐‐‐‐‐+‐‐‐‐‐‐‐‐‐‐‐‐‐‐‐‐‐‐‐+‐‐‐‐‐‐‐‐‐‐‐‐‐‐‐‐‐‐+‐‐‐‐‐‐‐‐‐‐‐‐‐‐‐‐‐+|         5 | ABNER             | ROSSELLETT       |      1252115.50 ||       500 | CANDICE           | BARTLETT         |      1384877.50 |+‐‐‐‐‐‐‐‐‐‐‐+‐‐‐‐‐‐‐‐‐‐‐‐‐‐‐‐‐‐‐+‐‐‐‐‐‐‐‐‐‐‐‐‐‐‐‐‐‐+‐‐‐‐‐‐‐‐‐‐‐‐‐‐‐‐‐+2 rows in set (4.01 sec)

Page 39: 10 things you might not know about MySQL

mysql> select * from v_client_portfolio_high;+‐‐‐‐‐‐‐‐‐‐‐+‐‐‐‐‐‐‐‐‐‐‐‐‐‐‐‐‐‐‐+‐‐‐‐‐‐‐‐‐‐‐‐‐‐‐‐‐‐+‐‐‐‐‐‐‐‐‐‐‐‐‐‐‐‐‐+| client_id | client_first_name | client_last_name | portfolio_value |+‐‐‐‐‐‐‐‐‐‐‐+‐‐‐‐‐‐‐‐‐‐‐‐‐‐‐‐‐‐‐+‐‐‐‐‐‐‐‐‐‐‐‐‐‐‐‐‐‐+‐‐‐‐‐‐‐‐‐‐‐‐‐‐‐‐‐+|         5 | ABNER             | ROSSELLETT       |      1252115.50 ||       500 | CANDICE           | BARTLETT         |      1384877.50 |+‐‐‐‐‐‐‐‐‐‐‐+‐‐‐‐‐‐‐‐‐‐‐‐‐‐‐‐‐‐‐+‐‐‐‐‐‐‐‐‐‐‐‐‐‐‐‐‐‐+‐‐‐‐‐‐‐‐‐‐‐‐‐‐‐‐‐+2 rows in set (4.01 sec) Why?

Page 40: 10 things you might not know about MySQL

mysql> set profiling=1;Query OK, 0 rows affected (0.00 sec)

mysql> select * from v_client_portfolio_high;+‐‐‐‐‐‐‐‐‐‐‐+‐‐‐‐‐‐‐‐‐‐‐‐‐‐‐‐‐‐‐+‐‐‐‐‐‐‐‐‐‐‐‐‐‐‐‐‐‐+‐‐‐‐‐‐‐‐‐‐‐‐‐‐‐‐‐+| client_id | client_first_name | client_last_name | portfolio_value |+‐‐‐‐‐‐‐‐‐‐‐+‐‐‐‐‐‐‐‐‐‐‐‐‐‐‐‐‐‐‐+‐‐‐‐‐‐‐‐‐‐‐‐‐‐‐‐‐‐+‐‐‐‐‐‐‐‐‐‐‐‐‐‐‐‐‐+|         5 | ABNER             | ROSSELLETT       |      1252115.50 ||       500 | CANDICE           | BARTLETT         |      1384877.50 |+‐‐‐‐‐‐‐‐‐‐‐+‐‐‐‐‐‐‐‐‐‐‐‐‐‐‐‐‐‐‐+‐‐‐‐‐‐‐‐‐‐‐‐‐‐‐‐‐‐+‐‐‐‐‐‐‐‐‐‐‐‐‐‐‐‐‐+2 rows in set (4.01 sec)

mysql> show profiles;+‐‐‐‐‐‐‐‐‐‐+‐‐‐‐‐‐‐‐‐‐‐‐+‐‐‐‐‐‐‐‐‐‐‐‐‐‐‐‐‐‐‐‐‐‐‐‐‐‐‐‐‐‐‐‐‐‐‐‐‐‐‐‐‐‐‐‐‐‐‐+| Query_ID | Duration   | Query                                         |+‐‐‐‐‐‐‐‐‐‐+‐‐‐‐‐‐‐‐‐‐‐‐+‐‐‐‐‐‐‐‐‐‐‐‐‐‐‐‐‐‐‐‐‐‐‐‐‐‐‐‐‐‐‐‐‐‐‐‐‐‐‐‐‐‐‐‐‐‐‐+|        1 | 0.00007600 | set profiling=1                               ||        2 | 4.01965600 | select * from v_client_portfolio_high         |+‐‐‐‐‐‐‐‐‐‐+‐‐‐‐‐‐‐‐‐‐‐‐+‐‐‐‐‐‐‐‐‐‐‐‐‐‐‐‐‐‐‐‐‐‐‐‐‐‐‐‐‐‐‐‐‐‐‐‐‐‐‐‐‐‐‐‐‐‐‐+

Page 41: 10 things you might not know about MySQL

mysql> select min(seq) seq,state,count(*) numb_ops,    ‐> round(sum(duration),5) sum_dur, round(avg(duration),5) avg_dur,    ‐> round(sum(cpu_user),5) sum_cpu, round(avg(cpu_user),5) avg_cpu    ‐> from information_schema.profiling    ‐> where query_id = 2    ‐> group by state    ‐> order by seq;+‐‐‐‐‐‐‐+‐‐‐‐‐‐‐‐‐‐‐‐‐‐‐‐‐‐‐‐‐‐+‐‐‐‐‐‐‐‐‐‐+‐‐‐‐‐‐‐‐‐+‐‐‐‐‐‐‐‐‐+‐‐‐‐‐‐‐‐‐+‐‐‐‐‐‐‐‐‐+| seq   | state                | numb_ops | sum_dur | avg_dur | sum_cpu | avg_cpu |+‐‐‐‐‐‐‐+‐‐‐‐‐‐‐‐‐‐‐‐‐‐‐‐‐‐‐‐‐‐+‐‐‐‐‐‐‐‐‐‐+‐‐‐‐‐‐‐‐‐+‐‐‐‐‐‐‐‐‐+‐‐‐‐‐‐‐‐‐+‐‐‐‐‐‐‐‐‐+|     0 | (initialization)     |        1 | 0.00004 | 0.00004 | 0.00000 | 0.00000 ||     1 | Opening tables       |        1 | 0.00023 | 0.00023 | 0.00000 | 0.00000 ||     2 | System lock          |        1 | 0.00001 | 0.00001 | 0.00000 | 0.00000 ||     3 | Table lock           |        1 | 0.00001 | 0.00001 | 0.00000 | 0.00000 ||     4 | checking permissions |        1 | 0.00010 | 0.00010 | 0.00000 | 0.00000 ||     5 | optimizing           |        4 | 0.00004 | 0.00001 | 0.00000 | 0.00000 ||     6 | statistics           |        4 | 0.00007 | 0.00002 | 0.00100 | 0.00025 ||     7 | preparing            |        4 | 0.00005 | 0.00001 | 0.00000 | 0.00000 ||     8 | Creating tmp table   |        1 | 0.00003 | 0.00003 | 0.00000 | 0.00000 ||     9 | executing            |    37352 | 0.16631 | 0.00000 | 0.05899 | 0.00000 ||    10 | Copying to tmp table |        1 | 0.00006 | 0.00006 | 0.00000 | 0.00000 ||    15 | Sending data         |    37353 | 3.85151 | 0.00010 | 3.72943 | 0.00010 || 74717 | Sorting result       |        1 | 0.00112 | 0.00112 | 0.00100 | 0.00100 || 74719 | removing tmp table   |        2 | 0.00003 | 0.00001 | 0.00000 | 0.00000 || 74721 | init                 |        1 | 0.00002 | 0.00002 | 0.00000 | 0.00000 || 74727 | end                  |        1 | 0.00001 | 0.00001 | 0.00000 | 0.00000 || 74728 | query end            |        1 | 0.00000 | 0.00000 | 0.00000 | 0.00000 || 74729 | freeing items        |        1 | 0.00002 | 0.00002 | 0.00000 | 0.00000 || 74730 | closing tables       |        2 | 0.00001 | 0.00001 | 0.00000 | 0.00000 || 74733 | logging slow query   |        1 | 0.00000 | 0.00000 | 0.00000 | 0.00000 |+‐‐‐‐‐‐‐+‐‐‐‐‐‐‐‐‐‐‐‐‐‐‐‐‐‐‐‐‐‐+‐‐‐‐‐‐‐‐‐‐+‐‐‐‐‐‐‐‐‐+‐‐‐‐‐‐‐‐‐+‐‐‐‐‐‐‐‐‐+‐‐‐‐‐‐‐‐‐+

Page 43: 10 things you might not know about MySQL

8Know what’s going on

Usage statistics

Page 44: 10 things you might not know about MySQL

SHOW STATUSmysql> SHOW STATUS LIKE 'Com_select';+‐‐‐‐‐‐‐‐‐‐‐‐‐‐‐+‐‐‐‐‐‐‐+| Variable_name | Value |+‐‐‐‐‐‐‐‐‐‐‐‐‐‐‐+‐‐‐‐‐‐‐+| Com_select    | 13    | +‐‐‐‐‐‐‐‐‐‐‐‐‐‐‐+‐‐‐‐‐‐‐+1 row in set (1.65 sec)

mysql> SELECT 1;+‐‐‐+| 1 |+‐‐‐+| 1 | +‐‐‐+1 row in set (0.00 sec)

mysql> SHOW STATUS LIKE 'Com_select';+‐‐‐‐‐‐‐‐‐‐‐‐‐‐‐+‐‐‐‐‐‐‐+| Variable_name | Value |+‐‐‐‐‐‐‐‐‐‐‐‐‐‐‐+‐‐‐‐‐‐‐+| Com_select    | 14    | +‐‐‐‐‐‐‐‐‐‐‐‐‐‐‐+‐‐‐‐‐‐‐+1 row in set (0.00 sec)

Page 45: 10 things you might not know about MySQL

SHOW STATUSmysql> SHOW STATUS LIKE 'Com_select';+‐‐‐‐‐‐‐‐‐‐‐‐‐‐‐+‐‐‐‐‐‐‐+| Variable_name | Value |+‐‐‐‐‐‐‐‐‐‐‐‐‐‐‐+‐‐‐‐‐‐‐+| Com_select    | 14    | +‐‐‐‐‐‐‐‐‐‐‐‐‐‐‐+‐‐‐‐‐‐‐+1 row in set (0.00 sec)

mysql> FLUSH STATUS;Query OK, 0 rows affected (0.00 sec)

mysql> SHOW STATUS LIKE 'Com_select';+‐‐‐‐‐‐‐‐‐‐‐‐‐‐‐+‐‐‐‐‐‐‐+| Variable_name | Value |+‐‐‐‐‐‐‐‐‐‐‐‐‐‐‐+‐‐‐‐‐‐‐+| Com_select    | 0     | +‐‐‐‐‐‐‐‐‐‐‐‐‐‐‐+‐‐‐‐‐‐‐+1 row in set (0.00 sec)

Page 46: 10 things you might not know about MySQL

External tools

• mysqlsla

http://hackmysql.com/mysqlsla

mysqlsla parses, filters, analyzes and sorts MySQL slow, general, binary and microslow patched logs in order to create a customizable report of the queries and their meta-property values.

Page 47: 10 things you might not know about MySQL

External tools• mysqlidxchk

http://hackmysql.com/mysqlidxchk

mysqlidxchk (MySQL Index Checker) checks MySQL databases/tables for unused indexes. Given one or more slow, general, or "raw" log files, mysqlidxchk reports which indexes in the database schema are not used by the queries in the log files.

Page 48: 10 things you might not know about MySQL

9Understanding

REPLACE

Page 49: 10 things you might not know about MySQL

mysql> CREATE TABLE fk_relations (    ‐>   key1 INT NOT NULL PRIMARY KEY,    ‐>   key2 INT NOT NULL UNIQUE    ‐> );Query OK, 0 rows affected (0.02 sec)

mysql> INSERT INTO fk_relations VALUES (1,1), (2,2);Query OK, 2 rows affected (0.00 sec)Records: 2  Duplicates: 0  Warnings: 0

mysql> SELECT * FROM fk_relations;+‐‐‐‐‐‐+‐‐‐‐‐‐+| key1 | key2 |+‐‐‐‐‐‐+‐‐‐‐‐‐+|    1 |    1 | |    2 |    2 | +‐‐‐‐‐‐+‐‐‐‐‐‐+2 rows in set (0.00 sec)

Page 50: 10 things you might not know about MySQL
Page 51: 10 things you might not know about MySQL

mysql> REPLACE INTO fk_relations VALUES (1,3);Query OK, 2 rows affected (0.03 sec)

Page 52: 10 things you might not know about MySQL

mysql> REPLACE INTO fk_relations VALUES (1,3);Query OK, 2 rows affected (0.03 sec)

mysql> SELECT * FROM fk_relations;+‐‐‐‐‐‐+‐‐‐‐‐‐+| key1 | key2 |+‐‐‐‐‐‐+‐‐‐‐‐‐+|    1 |    3 | |    2 |    2 | +‐‐‐‐‐‐+‐‐‐‐‐‐+2 rows in set (0.00 sec)

mysql> REPLACE INTO fk_relations VALUES (1,2);Query OK, 3 rows affected (0.06 sec)

???

Page 53: 10 things you might not know about MySQL

mysql> REPLACE INTO fk_relations VALUES (1,2);Query OK, 3 rows affected (0.06 sec)

mysql> SELECT * FROM fk_relations;+‐‐‐‐‐‐+‐‐‐‐‐‐+| key1 | key2 |+‐‐‐‐‐‐+‐‐‐‐‐‐+|    1 |    2 | +‐‐‐‐‐‐+‐‐‐‐‐‐+1 row in set (0.00 sec)

Page 54: 10 things you might not know about MySQL

+‐‐‐‐‐‐+‐‐‐‐‐‐+| key1 | key2 |+‐‐‐‐‐‐+‐‐‐‐‐‐+|    1 |    3 | |    2 |    2 | +‐‐‐‐‐‐+‐‐‐‐‐‐+

mysql> REPLACE INTO fk_relations VALUES (1,2);‐‐ Equals...

Page 55: 10 things you might not know about MySQL

+‐‐‐‐‐‐+‐‐‐‐‐‐+| key1 | key2 |+‐‐‐‐‐‐+‐‐‐‐‐‐+|    1 |    3 | |    2 |    2 | +‐‐‐‐‐‐+‐‐‐‐‐‐+

mysql> REPLACE INTO fk_relations VALUES (1,2);‐‐ Equals...‐‐ key1 is PKmysql> DELETE FROM fk_relations WHERE key1 = 1;

Page 56: 10 things you might not know about MySQL

+‐‐‐‐‐‐+‐‐‐‐‐‐+| key1 | key2 |+‐‐‐‐‐‐+‐‐‐‐‐‐+|    2 |    2 | +‐‐‐‐‐‐+‐‐‐‐‐‐+

mysql> REPLACE INTO fk_relations VALUES (1,2);‐‐ Equals...‐‐ key1 is PKmysql> DELETE FROM fk_relations WHERE key1 = 1;‐‐ key2 is Uniquemysql> DELETE FROM fk_relations WHERE key2 = 2;

Page 57: 10 things you might not know about MySQL

+‐‐‐‐‐‐+‐‐‐‐‐‐+| key1 | key2 |+‐‐‐‐‐‐+‐‐‐‐‐‐+|    1 |    2 | +‐‐‐‐‐‐+‐‐‐‐‐‐+

mysql> REPLACE INTO fk_relations VALUES (1,2);‐‐ Equals...‐‐ key1 is PKmysql> DELETE FROM fk_relations WHERE key1 = 1;‐‐ key2 is Uniquemysql> DELETE FROM fk_relations WHERE key2 = 2;mysql> INSERT INTO fk_relations VALUES (1,2);

Page 58: 10 things you might not know about MySQL

That’s whymysql> REPLACE INTO fk_relations VALUES (1,2);Query OK, 3 rows affected (0.06 sec)

mysql> SELECT * FROM fk_relations;+‐‐‐‐‐‐+‐‐‐‐‐‐+| key1 | key2 |+‐‐‐‐‐‐+‐‐‐‐‐‐+|    1 |    2 | +‐‐‐‐‐‐+‐‐‐‐‐‐+1 row in set (0.00 sec)

Page 59: 10 things you might not know about MySQL

That’s whymysql> REPLACE INTO fk_relations VALUES (1,2);Query OK, 3 rows affected (0.06 sec)

mysql> SELECT * FROM fk_relations;+‐‐‐‐‐‐+‐‐‐‐‐‐+| key1 | key2 |+‐‐‐‐‐‐+‐‐‐‐‐‐+|    1 |    2 | +‐‐‐‐‐‐+‐‐‐‐‐‐+1 row in set (0.00 sec)

2 deletes + 1 insert

Page 60: 10 things you might not know about MySQL

10The good and bad

about temporary tables

Page 61: 10 things you might not know about MySQL

Performance

• Be careful with complex queries

• Extremely slow on large datasets

• Use summary tables instead

Page 62: 10 things you might not know about MySQL

Too complexselect d.dept_name, SUM(salary) from departments d LEFT JOIN dept_emp de USING (dept_no) LEFT JOIN salaries s USING (emp_no) where s.from_date >= '2000‐01‐01' and s.to_date < '2001‐01‐01' group by dept_no;

Page 63: 10 things you might not know about MySQL

Instead, split in twoselect d.dept_name, SUM(salary) from departments d LEFT JOIN dept_emp de USING (dept_no) LEFT JOIN salaries s USING (emp_no) where s.from_date >= '2000‐01‐01' and s.to_date < '2001‐01‐01' group by dept_no;

CREATE TEMPORARY TABLE salaries2000 SELECT * FROM salaries s WHERE s.from_date >= '2000‐01‐01' AND s.to_date < '2001‐01‐01';

SELECT d.dept_name, SUM(salary) FROM departments d LEFT JOIN dept_emp de USING (dept_no) LEFT JOIN salaries2000 s USING (emp_no) GROUP BY dept_no;

Page 64: 10 things you might not know about MySQL

Big performance gain(If indexes are in their place)

Page 65: 10 things you might not know about MySQL

Big performance gain(If indexes are in their place)

I’ve seen 10X!

Page 66: 10 things you might not know about MySQL

one more thing...

Page 67: 10 things you might not know about MySQL

one more thing...I had to do it ;-)

Page 68: 10 things you might not know about MySQL

Shit happensmysql> select * from t;+‐‐‐‐‐‐+| id   |+‐‐‐‐‐‐+|    2 | +‐‐‐‐‐‐+1 row in set (0.00 sec)

mysql> drop table t;Query OK, 0 rows affected (0.04 sec)

mysql> drop table t;Query OK, 0 rows affected (0.00 sec)

mysql> drop table t;ERROR 1051 (42S02): Unknown table 't'

WTF?!?

Page 69: 10 things you might not know about MySQL

Some seconds ago...

Page 70: 10 things you might not know about MySQL

mysql> select * from t;+‐‐‐‐+| id |+‐‐‐‐+|  1 | +‐‐‐‐+1 row in set (0.00 sec)

mysql> create temporary table t(id int);Query OK, 0 rows affected (0.08 sec)

mysql> select * from t;Empty set (0.00 sec)

mysql> insert into t values (2);Query OK, 1 row affected (0.05 sec)

mysql> select * from t;+‐‐‐‐‐‐+| id   |+‐‐‐‐‐‐+|    2 | +‐‐‐‐‐‐+1 row in set (0.00 sec)

WTF?!?...again

Page 71: 10 things you might not know about MySQL

• Temporary tables exist per session

• Be careful using connection pools

• They overlap current tables

Page 72: 10 things you might not know about MySQL

There’s a reason for everythingmysql> select * from t;+‐‐‐‐‐‐+| id   |+‐‐‐‐‐‐+|    2 | +‐‐‐‐‐‐+1 row in set (0.00 sec)

mysql> drop table t;Query OK, 0 rows affected (0.04 sec)

mysql> select * from t;+‐‐‐‐+| id |+‐‐‐‐+|  1 | +‐‐‐‐+1 row in set (0.00 sec)

mysql> drop table t;Query OK, 0 rows affected (0.00 sec)

mysql> drop table t;ERROR 1051 (42S02): Unknown table 't'

temporary

regular

Page 73: 10 things you might not know about MySQL

• MySQL Proxy

https://launchpad.net/mysql-proxy

• MySQL Sandbox

https://launchpad.net/mysql-sandbox

• MySQL Random Query Generator

https://launchpad.net/randgen

What else?

Page 74: 10 things you might not know about MySQL

Questions?Probably out of time at this point, but it’s the standard

Page 75: 10 things you might not know about MySQL

Thanks!