MySQL talk at J and Beyond 2014 about nested data sets, how to use them most efficiently, and other performance tips such as string lookup and indexing options.
20. PATH TO A NODE
SELECT GROUP_CONCAT(alias SEPARATOR '/') as
path
FROM con_menu
WHERE lft <= 20 AND rgt >= 21 AND lft > 1
ORDER BY lft ASC;
(Messaging/Read Private Message)
#JAB14 - @EliAschkenasy ¨C Integral DB Design
29. ? WHO AM I ?
? NESTED SET INTRO
? NESTED SET BASIC QUERIES
? NESTED SET BASIC QUERIES OPTIMIZATION
?
?
?
#JAB14 - @EliAschkenasy ¨C Integral DB Design
31. Common INSERT
INSERT INTO #__ (part_number, unit_price,
eau,¡.)
VALUES (¡.);
Common SELECT
SELECT unit_price FROM #__
WHERE part_number = $part_number;
#JAB14 - @EliAschkenasy ¨C Integral DB Design
32. Common INSERT
INSERT INTO #__ (part_number, unit_price,
eau,¡.)
VALUES (¡.);
Common SELECT
SELECT unit_price FROM #__
WHERE part_number = $part_number;
PROBLEMS:
1. Speed
2. Data accuracy (inconsistent white spacing)
#JAB14 - @EliAschkenasy ¨C Integral DB Design
33. Amended INSERT
php: $concat = preg_replace('/s+/', '', $input);
INSERT INTO #__ (part_number, unit_price,
eau,part_number_concat,¡)
VALUES (¡,$concat);
Amended SELECT
SELECT unit_price FROM #__
WHERE part_number_concat = $concat;
PROBLEMS:
1. Speed
2. Data accuracy (inconsistent white spacing)
#JAB14 - @EliAschkenasy ¨C Integral DB Design
34. Optimized INSERT
php: $concat = preg_replace('/s+/', '', $input);
php: $crc = crc32($concat);
INSERT INTO #__ (part_number, unit_price,
eau,part_number_concat,crc_partnumberconcat¡)
VALUES (¡,$concat,$crc);
Optimized SELECT
SELECT unit_price FROM #__
WHERE crc_partnumberconcat = $crc
AND part_number_concat = $concat; (singularity)
PROBLEMS:
1. Speed
2. Data accuracy (inconsistent white spacing)
#JAB14 - @EliAschkenasy ¨C Integral DB Design
35. Optimized INSERT
php: $concat = preg_replace('/s+/', '', $input);
php: $crc = crc32($concat);
INSERT INTO #__ (part_number, unit_price,
eau,part_number_concat,crc_partnumberconcat¡)
VALUES (¡,$concat,$crc);
Optimized SELECT
SELECT unit_price FROM #__
WHERE crc_partnumberconcat = $crc
AND part_number_concat = $concat; (singularity)
PROBLEMS:
1. Speed
2. Data accuracy (inconsistent 32bit vs 64bit)
#JAB14 - @EliAschkenasy ¨C Integral DB Design
36. Optimized INSERT
php: $concat = preg_replace('/s+/', '', $input);
INSERT INTO #__ (part_number, unit_price,
eau,part_number_concat,sha_partnumberconcat¡)
VALUES (¡,$concat,SHA1($concat));
Optimized SELECT
SELECT unit_price FROM #__
WHERE sha_partnumberconcat = SHA1($concat);
AND part_number_concat = $concat; (singularity)
PROBLEMS:
1. Speed
2. Data accuracy (inconsistent 32bit vs 64bit)
#JAB14 - @EliAschkenasy ¨C Integral DB Design
37. Optimized INSERT (* BATCH)
php: $concat = preg_replace('/s+/', '', $input);
ALTER TABLE #__ DROP INDEX x
INSERT INTO #__ (part_number, unit_price,
eau,part_number_concat,sha_partnumberconcat¡)
VALUES (¡,$concat concat,SHA1($concat));
ALTER TABLE #__ ADD INDEX x (¡®column¡¯)
#JAB14 - @EliAschkenasy ¨C Integral DB Design
38. Hits Counter Table
CREATE TABLE hit_counter (
cnt INT UNSIGNED NOT NULL DEFAULT 0
) ENGINE=InnoDB;
INSERT INTO hit_counter (cnt) VALUES (0);
UPDATE hit_counter SET cnt = cnt + 1;
SELECT cnt FROM hit_counter;
#JAB14 - @EliAschkenasy ¨C Integral DB Design
39. Hits Counter Table
CREATE TABLE hit_counter (
cnt INT UNSIGNED NOT NULL DEFAULT 0
) ENGINE=InnoDB;
INSERT INTO hit_counter (cnt) VALUES (0);
UPDATE hit_counter SET cnt = cnt + 1;
SELECT cnt FROM hit_counter;
#JAB14 - @EliAschkenasy ¨C Integral DB Design
Hits Counter Table (Optimized)
CREATE TABLE hit_counter (
slot TINYINT UNSIGNED NOT NULL PRIMARY KEY,
cnt INT UNSIGNED NOT NULL
) ENGINE=InnoDB;
INSERT INTO hit_counter VALUES
(0,0), (1,0), (2,0), (3,0), (4,0);
-- any amount of slots you require (n-1)
UPDATE hit_counter SET cnt = cnt + 1
WHERE slot = FLOOR(RAND() * 5);
-- the amount of slots you assigned
SELECT SUM(cnt) FROM hit_counter;
40. ? WHO AM I ?
? NESTED SET INTRO
? NESTED SET BASIC QUERIES
? NESTED SET BASIC QUERIES OPTIMIZATION
? STRING LOOKUP OPTIMIZATION TRICK
? INDEXING OPTIONS
?
#JAB14 - @EliAschkenasy ¨C Integral DB Design
41. #JAB14 - @EliAschkenasy ¨C Integral DB Design
SELECT * FROM Orgchart SELECT a, c FROM Orgchart SELECT a, c FROM Orgchart
WHERE lft - rgt = 1; WHERE lft - rgt = 1; WHERE lft =(rgt ¨C 1);
SELECT name FROM people mysql> ALTER TABLE people ADD KEY (idx_name(6));
WHERE name = ¡®Hans¡¯;
CREATE TABLE t ( KEY(c1,c2,c3) ? KEY(c1,c3) Specificity!
c1 INT,
c2 INT,
c3 INT,
KEY(c1),
KEY(c2),
KEY(c3)
);
42. #JAB14 - @EliAschkenasy ¨C Integral DB Design
SELECT * FROM Orgchart SELECT a, c FROM Orgchart SELECT a, c FROM Orgchart
WHERE lft - rgt = 1; WHERE lft - rgt = 1; WHERE lft =(rgt ¨C 1);
SELECT name FROM people mysql> ALTER TABLE people ADD KEY (idx_name(6));
WHERE name = ¡®Hans¡¯;
CREATE TABLE t ( KEY(c1,c2,c3) ? KEY(c1,c3) Specificity!
c1 INT,
c2 INT,
c3 INT,
KEY(c1),
KEY(c2),
KEY(c3)
);
SELECT cc FROM payment WHERE staff_id = 2 AND customer_id = 584;
KEY(staff_id,customer_id) ?
SELECT SUM(staff_id = 2), SUM(customer_id = 584) FROM paymentG
** 1. row **
SUM(staff_id = 2): 7992
SUM(customer_id = 584): 30
ALTER TABLE payment ADD KEY(customer_id, staff_id);
43. #JAB14 - @EliAschkenasy ¨C Integral DB Design
CREATE TABLE profile(
id INT UNSIGNED NOT NULL AUTO_INCREMENT,
sex CHAR(1) NOT NULL,
age TINYINT NOT NULL,
country VARCHAR(255) NOT NULL,
region VARCHAR(255) NOT NULL DEFAULT ¡®¡¯,
city VARCHAR(255) NOT NULL DEFAULT ¡®¡¯,
color_hair VARCHAR(255) NOT NULL DEFAULT ¡®¡¯,
color_eyes VARCHAR(255) NOT NULL DEFAULT ¡®¡¯,
name
¡
¡
rating TINYINT NOT NULL DEFAULT 1,
PRIMARY KEY(id)
);
44. #JAB14 - @EliAschkenasy ¨C Integral DB Design
CREATE TABLE profile(
id INT UNSIGNED NOT NULL AUTO_INCREMENT,
sex CHAR(1) NOT NULL,
age TINYINT NOT NULL,
country VARCHAR(255) NOT NULL,
region VARCHAR(255) NOT NULL DEFAULT ¡®¡¯,
city VARCHAR(255) NOT NULL DEFAULT ¡®¡¯,
color_hair VARCHAR(255) NOT NULL DEFAULT ¡®¡¯,
color_eyes VARCHAR(255) NOT NULL DEFAULT ¡®¡¯,
name
¡
¡
rating TINYINT NOT NULL DEFAULT 1,
PRIMARY KEY(id)
);
WHERE age BETWEEN 18 AND 25
ORDER BY rating ASC
MySQL can¡¯t use added index if primary
index uses range criterion
KEY(sex, country)
NO Selectivity!!!
KEY(sex, country)
Assumption: all searches will include sex and
most will include country
Trick: AND sex IN('m', 'f')
45. #JAB14 - @EliAschkenasy ¨C Integral DB Design
CREATE TABLE profile(
id INT UNSIGNED NOT NULL AUTO_INCREMENT,
sex CHAR(1) NOT NULL,
age TINYINT NOT NULL,
country VARCHAR(255) NOT NULL,
region VARCHAR(255) NOT NULL DEFAULT ¡®¡¯,
city VARCHAR(255) NOT NULL DEFAULT ¡®¡¯,
color_hair VARCHAR(255) NOT NULL DEFAULT ¡®¡¯,
color_eyes VARCHAR(255) NOT NULL DEFAULT ¡®¡¯,
name
¡
¡
rating TINYINT NOT NULL DEFAULT 1,
PRIMARY KEY(id)
);
(sex, country, age)
(sex, country, region, age)
(sex, country, region, city, age)
Using the IN() trick, we can implement just
the
(sex, country, region, city, age) index.
Why is age at end?
Remember our range problem?
MySQL uses indexes from left to right until
the first range query
Trick: Convert WHERE age BETWEEN 18 and 25 to
WHERE age IN(18,19,20,21,22,23,24,25)