ºÝºÝߣ

ºÝºÝߣShare a Scribd company logo
#JAB14 - @EliAschkenasy ¨C Integral DB Design
?
?
?
?
?
?
?
#JAB14 - @EliAschkenasy ¨C Integral DB Design
? WHO AM I ?
?
?
?
?
?
?
#JAB14 - @EliAschkenasy ¨C Integral DB Design
#JAB14 - @EliAschkenasy ¨C Integral DB Design
#JAB14 - @EliAschkenasy ¨C Integral DB Design
#JAB14 - @EliAschkenasy ¨C Integral DB Design
MySQL Integral DB Design #JAB14
Categories
Articles
Root Node
1
2
3
4 5
lft rgt
1 36
2 15
3 8
4 5
6 7
9 14
10 11
12 13
16 21
17 18
19 20
22 35
23 28
24 25
26 27
29 34
30 31
32 33
6 7
8 9
1
0
1
1
1
2
1
3
1
4
1
5
1
6
1
7
1
8
1
9
2
0
2
1
2
2
3
5
2
3
2
8
2
4
2
5
2
6
2
7
2
9
3
4
3
0
3
2
3
1
3
3
3
6
#JAB14 - @EliAschkenasy ¨C Integral DB Design
Root Node
1
2
3
4 5
lft rgt
1 36
2 15
3 8
4 5
6 7
9 14
10 11
12 13
16 21
17 18
19 20
22 35
23 28
24 25
26 27
29 34
30 31
32 33
6 7
8 9
1
0
1
1
1
2
1
3
1
4
1
5
1
6
1
7
1
8
1
9
2
0
2
1
2
2
3
5
2
3
2
8
2
4
2
5
2
6
2
7
2
9
3
4
3
0
3
2
3
1
3
3
3
6
ROOT NODE
root = lft == 1
#JAB14 - @EliAschkenasy ¨C Integral DB Design
Root Node
1
2
3
4 5
lft rgt
1 36
2 15
3 8
4 5
6 7
9 14
10 11
12 13
16 21
17 18
19 20
22 35
23 28
24 25
26 27
29 34
30 31
32 33
6 7
8 9
1
0
1
1
1
2
1
3
1
4
1
5
1
6
1
7
1
8
1
9
2
0
2
1
2
2
3
5
2
3
2
8
2
4
2
5
2
6
2
7
2
9
3
4
3
0
3
2
3
1
3
3
3
6
TOTAL NODES
(rgt ¨C lft + 1) / 2 = total
(36 ¨C 1 + 1) / 2 = 18
#JAB14 - @EliAschkenasy ¨C Integral DB Design
Root Node
1
2
3
4 5
lft rgt
1 36
2 15
3 8
4 5
6 7
9 14
10 11
12 13
16 21
17 18
19 20
22 35
23 28
24 25
26 27
29 34
30 31
32 33
6 7
8 9
1
0
1
1
1
2
1
3
1
4
1
5
1
6
1
7
1
8
1
9
2
0
2
1
2
2
3
5
2
3
2
8
2
4
2
5
2
6
2
7
2
9
3
4
3
0
3
2
3
1
3
3
3
6
IS LEAF NODE?
leaf = (rgt ¨C lft ==1) ? true : false;
true = (5 ¨C 4 == 1)
false = (8 ¨C 3 == 1)
#JAB14 - @EliAschkenasy ¨C Integral DB Design
Root Node
1
2
3
4 5
lft rgt
1 36
2 15
3 8
4 5
6 7
9 14
10 11
12 13
16 21
17 18
19 20
22 35
23 28
24 25
26 27
29 34
30 31
32 33
6 7
8 9
1
0
1
1
1
2
1
3
1
4
1
5
1
6
1
7
1
8
1
9
2
0
2
1
2
2
3
5
2
3
2
8
2
4
2
5
2
6
2
7
2
9
3
4
3
0
3
2
3
1
3
3
3
6
LEAF NODE OPTIMIZATION
Optimized implementation
SELECT x, x, x
FROM #__
WHERE lft = (rgt -1)
#JAB14 - @EliAschkenasy ¨C Integral DB Design
Root Node
1
2
3
4 5
lft rgt
1 36
2 15
3 8
4 5
6 7
9 14
10 11
12 13
16 21
17 18
19 20
22 35
23 28
24 25
26 27
29 34
30 31
32 33
6 7
8 9
1
0
1
1
1
2
1
3
1
4
1
5
1
6
1
7
1
8
1
9
2
0
2
1
2
2
3
5
2
3
2
8
2
4
2
5
2
6
2
7
2
9
3
4
3
0
3
2
3
1
3
3
3
6
SUBTREE SELECTION OPTIMIZATION
SELECT c.type AS choices, b.type AS
bottom
FROM #__ AS c, #__ AS b
WHERE c.lft BETWEEN b.lft AND b.rgt;
Anything between 22 and 35
#JAB14 - @EliAschkenasy ¨C Integral DB Design
Root Node
1
2
3
4 5
lft rgt
1 36
2 15
3 8
4 5
6 7
9 14
10 11
12 13
16 21
17 18
19 20
22 35
23 28
24 25
26 27
29 34
30 31
32 33
6 7
8 9
1
0
1
1
1
2
1
3
1
4
1
5
1
6
1
7
1
8
1
9
2
0
2
1
2
2
3
5
2
3
2
8
2
4
2
5
2
6
2
7
2
9
3
4
3
0
3
2
3
1
3
3
3
6
SUBTREE SELECTION ONLY SUBTREE
Optimized implementation
SELECT c.type AS choices, b.type AS
bottom
FROM #__ AS c, #__ AS b
WHERE c.lft BETWEEN (b.lft+1) AND b.rgt;
Anyone between 23and 35
#JAB14 - @EliAschkenasy ¨C Integral DB Design
Root Node
1
2
3
4 5
lft rgt
1 36
2 15
3 8
4 5
6 7
9 14
10 11
12 13
16 21
17 18
19 20
22 35
23 28
24 25
26 27
29 34
30 31
32 33
6 7
8 9
1
0
1
1
1
2
1
3
1
4
1
5
1
6
1
7
1
8
1
9
2
0
2
1
2
2
3
5
2
3
2
8
2
4
2
5
2
6
2
7
2
9
3
4
3
0
3
2
3
1
3
3
3
6
#JAB14 - @EliAschkenasy ¨C Integral DB Design
Root Node
1
2
3
4 5
lft rgt
1 36
2 15
3 8
4 5
6 7
9 14
10 11
12 13
16 21
17 18
19 20
22 35
23 28
24 25
26 27
29 34
30 31
32 33
6 7
8 9
1
0
1
1
1
2
1
3
1
4
1
5
1
6
1
7
1
8
1
9
2
0
2
1
2
2
3
5
2
3
2
8
2
4
2
5
2
6
2
7
2
9
3
4
3
0
3
2
3
1
3
3
3
6
#JAB14 - @EliAschkenasy ¨C Integral DB Design
Root Node
1
2
3
4 5
lft rgt
1 36
2 15
3 8
4 5
6 7
9 14
10 11
12 13
16 21
17 18
19 20
22 35
23 28
24 25
26 27
29 34
30 31
32 33
6 7
8 9
1
0
1
1
1
2
1
3
1
4
1
5
1
6
1
7
1
8
1
9
2
0
2
1
2
2
3
5
2
3
2
8
2
4
2
5
2
6
2
7
2
9
3
4
3
0
3
2
3
1
3
3
3
6
PATH TO A NODE (breadcrumb)
SELECT alias
FROM #__
WHERE lft < 4 AND rgt > 5
ORDER BY lft ASC;
#JAB14 - @EliAschkenasy ¨C Integral DB Design
Root Node
1
2
3
4 5
lft rgt
1 36
2 15
3 8
4 5
6 7
9 14
10 11
12 13
16 21
17 18
19 20
22 35
23 28
24 25
26 27
29 34
30 31
32 33
6 7
8 9
1
0
1
1
1
2
1
3
1
4
1
5
1
6
1
7
1
8
1
9
2
0
2
1
2
2
3
5
2
3
2
8
2
4
2
5
2
6
2
7
2
9
3
4
3
0
3
2
3
1
3
3
3
6
PATH TO A NODE
SELECT GROUP_CONCAT(alias SEPARATOR '/') as
path
FROM options
WHERE lft <= 4 AND rgt >= 5
ORDER BY lft ASC;
(sandal/blouse/skirt/woman)
#JAB14 - @EliAschkenasy ¨C Integral DB Design
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
Root Node
1
2
3
4 5
lft rgt
1 36
2 15
3 8
4 5
6 7
9 14
10 11
12 13
16 21
17 18
19 20
22 35
23 28
24 25
26 27
29 34
30 31
32 33
6 7
8 9
1
0
1
1
1
2
1
3
1
4
1
5
1
6
1
7
1
8
1
9
2
0
2
1
2
2
3
5
2
3
2
8
2
4
2
5
2
6
2
7
2
9
3
4
3
0
3
2
3
1
3
3
3
6
#JAB14 - @EliAschkenasy ¨C Integral DB Design
Root Node
1
2
3
4 5
lft rgt
1 36
2 15
3 8
4 5
6 7
9 14
10 11
12 13
16 21
17 18
19 20
22 35
23 28
24 25
26 27
29 34
30 31
32 33
6 7
8 9
1
0
1
1
1
2
1
3
1
4
1
5
1
6
1
7
1
8
1
9
2
0
2
1
2
2
3
5
2
3
2
8
2
4
2
5
2
6
2
7
2
9
3
4
3
0
3
2
3
1
3
3
3
6
LEVEL OF NODE
SELECT b.id, COUNT(a.id) AS level
FROM #__ AS a, #__ AS b
WHERE b.lft BETWEEN a.lft AND a.rgt
AND a.lft = 19
GROUP BY b.id
#JAB14 - @EliAschkenasy ¨C Integral DB Design
Root Node
1
2
3
4 5
lft rgt
1 36
2 15
3 8
4 5
6 7
9 14
10 11
12 13
16 21
17 18
19 20
22 35
23 28
24 25
26 27
29 34
30 31
32 33
6 7
8 9
1
0
1
1
1
2
1
3
1
4
1
5
1
6
1
7
1
8
1
9
2
0
2
1
2
2
3
5
2
3
2
8
2
4
2
5
2
6
2
7
2
9
3
4
3
0
3
2
3
1
3
3
3
6
#JAB14 - @EliAschkenasy ¨C Integral DB Design
Root Node
1
2
3
4 5
lft rgt
1 36
2 15
3 8
4 5
6 7
9 14
10 11
12 13
16 21
17 18
19 20
22 35
23 28
24 25
26 27
29 34
30 31
32 33
6 7
8 9
1
0
1
1
1
2
1
3
1
4
1
5
1
6
1
7
1
8
1
9
2
0
2
1
2
2
3
5
2
3
2
8
2
4
2
5
2
6
2
7
2
9
3
4
3
0
3
2
3
1
3
3
3
6
PARENT ID OF A NODE
SELECT id, (SELECT id
FROM #__ t2
WHERE t2.lft < t1.lft AND t2.rgt > t1.rgt
ORDER BY t2.rgt-t1.rgt ASC
LIMIT 1)
AS parentid FROM #__ t1
ORDER BY (rgt-lft) DESC
#JAB14 - @EliAschkenasy ¨C Integral DB Design
Root Node
1
2
3
4 5
lft rgt
1 36
2 15
3 8
4 5
6 7
9 14
10 11
12 13
16 21
17 18
19 20
22 35
23 28
24 25
26 27
29 34
30 31
32 33
6 7
8 9
1
0
1
1
1
2
1
3
1
4
1
5
1
6
1
7
1
8
1
9
2
0
2
1
2
2
3
5
2
3
2
8
2
4
2
5
2
6
2
7
2
9
3
4
3
0
3
2
3
1
3
3
3
6
MAXIMUM DEPTH
SELECT MAX(level) AS height
FROM (
SELECT b.id, (COUNT(a.id) - 1) AS level
FROM #__ AS a, #__ AS b
WHERE b.lft BETWEEN a.lft AND a.rgt
GROUP BY b.id
) AS L1
#JAB14 - @EliAschkenasy ¨C Integral DB Design
Root Node
1
2
3
4 5
lft rgt
1 36
2 15
3 8
4 5
6 7
9 14
10 11
12 13
16 21
17 18
19 20
22 35
23 28
24 25
26 27
29 34
30 31
32 33
6 7
8 9
1
0
1
1
1
2
1
3
1
4
1
5
1
6
1
7
1
8
1
9
2
0
2
1
2
2
3
5
2
3
2
8
2
4
2
5
2
6
2
7
2
9
3
4
3
0
3
2
3
1
3
3
3
6
INSERT A NODE
UPDATE #__ SET rgt=rgt+2 WHERE rgt >= 25;
UPDATE #__ SET lft=lft+2 WHERE lft >= 24;
INSERT INTO #__ SET lft=24, rgt=25, ¡­.;
#JAB14 - @EliAschkenasy ¨C Integral DB Design
Root Node
1
2
3
4 5
lft rgt
1 36
2 15
3 8
4 5
6 7
9 14
10 11
12 13
16 21
17 18
19 20
22 35
23 28
24 25
26 27
29 34
30 31
32 33
6 7
8 9
1
0
1
1
1
2
1
3
1
4
1
5
1
6
1
7
1
8
1
9
2
0
2
1
2
2
3
5
2
3
2
8
2
4
2
5
2
6
2
7
2
9
3
4
3
0
3
2
3
1
3
3
3
6
INSERT A NODE
UPDATE #__ SET rgt=rgt+2 WHERE rgt >= 25;
UPDATE #__ SET lft=lft+2 WHERE lft >= 24;
INSERT INTO #__ SET lft=24, rgt=25, ¡­.;
#JAB14 - @EliAschkenasy ¨C Integral DB Design
Root Node
1
2
3
4 5
lft rgt
1 36
2 15
3 8
4 5
6 7
9 14
10 11
12 13
16 21
17 18
19 20
22 35
23 28
24 25
26 27
29 34
30 31
32 33
6 7
8 9
1
0
1
1
1
2
1
3
1
4
1
5
1
6
1
7
1
8
1
9
2
0
2
1
2
2
3
7
2
3
3
0
2
6
2
7
2
8
2
9
3
1
3
6
3
2
3
4
3
3
3
5
3
8
INSERT A NODE
UPDATE #__ SET rgt=rgt+2 WHERE rgt >= 25;
UPDATE #__ SET lft=lft+2 WHERE lft >= 24;
INSERT INTO #__ SET lft=24, rgt=25, ¡­.;
2
4
2
5
#JAB14 - @EliAschkenasy ¨C Integral DB Design
? WHO AM I ?
? NESTED SET INTRO
? NESTED SET BASIC QUERIES
? NESTED SET BASIC QUERIES OPTIMIZATION
?
?
?
#JAB14 - @EliAschkenasy ¨C Integral DB Design
#JAB14 - @EliAschkenasy ¨C Integral DB Design
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
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
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
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
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
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
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
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
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;
? 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
#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)
);
#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);
#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)
);
#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')
#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)
#JAB14 - @EliAschkenasy ¨C Integral DB Design
?
#JAB14 - @EliAschkenasy ¨C Integral DB Design
?
?
#JAB14 - @EliAschkenasy ¨C Integral DB Design
?
?
?
#JAB14 - @EliAschkenasy ¨C Integral DB Design
?
?
?
?
#JAB14 - @EliAschkenasy ¨C Integral DB Design
?
?
?
?
?
#JAB14 - @EliAschkenasy ¨C Integral DB Design
?
?
?
?
?
?
#JAB14 - @EliAschkenasy ¨C Integral DB Design
?
?
?
?
?
?
?
#JAB14 - @EliAschkenasy ¨C Integral DB Design
#JAB14 - @EliAschkenasy ¨C Integral DB Design

More Related Content

MySQL Integral DB Design #JAB14

  • 1. #JAB14 - @EliAschkenasy ¨C Integral DB Design
  • 2. ? ? ? ? ? ? ? #JAB14 - @EliAschkenasy ¨C Integral DB Design
  • 3. ? WHO AM I ? ? ? ? ? ? ? #JAB14 - @EliAschkenasy ¨C Integral DB Design
  • 4. #JAB14 - @EliAschkenasy ¨C Integral DB Design
  • 5. #JAB14 - @EliAschkenasy ¨C Integral DB Design
  • 6. #JAB14 - @EliAschkenasy ¨C Integral DB Design
  • 9. Root Node 1 2 3 4 5 lft rgt 1 36 2 15 3 8 4 5 6 7 9 14 10 11 12 13 16 21 17 18 19 20 22 35 23 28 24 25 26 27 29 34 30 31 32 33 6 7 8 9 1 0 1 1 1 2 1 3 1 4 1 5 1 6 1 7 1 8 1 9 2 0 2 1 2 2 3 5 2 3 2 8 2 4 2 5 2 6 2 7 2 9 3 4 3 0 3 2 3 1 3 3 3 6 #JAB14 - @EliAschkenasy ¨C Integral DB Design
  • 10. Root Node 1 2 3 4 5 lft rgt 1 36 2 15 3 8 4 5 6 7 9 14 10 11 12 13 16 21 17 18 19 20 22 35 23 28 24 25 26 27 29 34 30 31 32 33 6 7 8 9 1 0 1 1 1 2 1 3 1 4 1 5 1 6 1 7 1 8 1 9 2 0 2 1 2 2 3 5 2 3 2 8 2 4 2 5 2 6 2 7 2 9 3 4 3 0 3 2 3 1 3 3 3 6 ROOT NODE root = lft == 1 #JAB14 - @EliAschkenasy ¨C Integral DB Design
  • 11. Root Node 1 2 3 4 5 lft rgt 1 36 2 15 3 8 4 5 6 7 9 14 10 11 12 13 16 21 17 18 19 20 22 35 23 28 24 25 26 27 29 34 30 31 32 33 6 7 8 9 1 0 1 1 1 2 1 3 1 4 1 5 1 6 1 7 1 8 1 9 2 0 2 1 2 2 3 5 2 3 2 8 2 4 2 5 2 6 2 7 2 9 3 4 3 0 3 2 3 1 3 3 3 6 TOTAL NODES (rgt ¨C lft + 1) / 2 = total (36 ¨C 1 + 1) / 2 = 18 #JAB14 - @EliAschkenasy ¨C Integral DB Design
  • 12. Root Node 1 2 3 4 5 lft rgt 1 36 2 15 3 8 4 5 6 7 9 14 10 11 12 13 16 21 17 18 19 20 22 35 23 28 24 25 26 27 29 34 30 31 32 33 6 7 8 9 1 0 1 1 1 2 1 3 1 4 1 5 1 6 1 7 1 8 1 9 2 0 2 1 2 2 3 5 2 3 2 8 2 4 2 5 2 6 2 7 2 9 3 4 3 0 3 2 3 1 3 3 3 6 IS LEAF NODE? leaf = (rgt ¨C lft ==1) ? true : false; true = (5 ¨C 4 == 1) false = (8 ¨C 3 == 1) #JAB14 - @EliAschkenasy ¨C Integral DB Design
  • 13. Root Node 1 2 3 4 5 lft rgt 1 36 2 15 3 8 4 5 6 7 9 14 10 11 12 13 16 21 17 18 19 20 22 35 23 28 24 25 26 27 29 34 30 31 32 33 6 7 8 9 1 0 1 1 1 2 1 3 1 4 1 5 1 6 1 7 1 8 1 9 2 0 2 1 2 2 3 5 2 3 2 8 2 4 2 5 2 6 2 7 2 9 3 4 3 0 3 2 3 1 3 3 3 6 LEAF NODE OPTIMIZATION Optimized implementation SELECT x, x, x FROM #__ WHERE lft = (rgt -1) #JAB14 - @EliAschkenasy ¨C Integral DB Design
  • 14. Root Node 1 2 3 4 5 lft rgt 1 36 2 15 3 8 4 5 6 7 9 14 10 11 12 13 16 21 17 18 19 20 22 35 23 28 24 25 26 27 29 34 30 31 32 33 6 7 8 9 1 0 1 1 1 2 1 3 1 4 1 5 1 6 1 7 1 8 1 9 2 0 2 1 2 2 3 5 2 3 2 8 2 4 2 5 2 6 2 7 2 9 3 4 3 0 3 2 3 1 3 3 3 6 SUBTREE SELECTION OPTIMIZATION SELECT c.type AS choices, b.type AS bottom FROM #__ AS c, #__ AS b WHERE c.lft BETWEEN b.lft AND b.rgt; Anything between 22 and 35 #JAB14 - @EliAschkenasy ¨C Integral DB Design
  • 15. Root Node 1 2 3 4 5 lft rgt 1 36 2 15 3 8 4 5 6 7 9 14 10 11 12 13 16 21 17 18 19 20 22 35 23 28 24 25 26 27 29 34 30 31 32 33 6 7 8 9 1 0 1 1 1 2 1 3 1 4 1 5 1 6 1 7 1 8 1 9 2 0 2 1 2 2 3 5 2 3 2 8 2 4 2 5 2 6 2 7 2 9 3 4 3 0 3 2 3 1 3 3 3 6 SUBTREE SELECTION ONLY SUBTREE Optimized implementation SELECT c.type AS choices, b.type AS bottom FROM #__ AS c, #__ AS b WHERE c.lft BETWEEN (b.lft+1) AND b.rgt; Anyone between 23and 35 #JAB14 - @EliAschkenasy ¨C Integral DB Design
  • 16. Root Node 1 2 3 4 5 lft rgt 1 36 2 15 3 8 4 5 6 7 9 14 10 11 12 13 16 21 17 18 19 20 22 35 23 28 24 25 26 27 29 34 30 31 32 33 6 7 8 9 1 0 1 1 1 2 1 3 1 4 1 5 1 6 1 7 1 8 1 9 2 0 2 1 2 2 3 5 2 3 2 8 2 4 2 5 2 6 2 7 2 9 3 4 3 0 3 2 3 1 3 3 3 6 #JAB14 - @EliAschkenasy ¨C Integral DB Design
  • 17. Root Node 1 2 3 4 5 lft rgt 1 36 2 15 3 8 4 5 6 7 9 14 10 11 12 13 16 21 17 18 19 20 22 35 23 28 24 25 26 27 29 34 30 31 32 33 6 7 8 9 1 0 1 1 1 2 1 3 1 4 1 5 1 6 1 7 1 8 1 9 2 0 2 1 2 2 3 5 2 3 2 8 2 4 2 5 2 6 2 7 2 9 3 4 3 0 3 2 3 1 3 3 3 6 #JAB14 - @EliAschkenasy ¨C Integral DB Design
  • 18. Root Node 1 2 3 4 5 lft rgt 1 36 2 15 3 8 4 5 6 7 9 14 10 11 12 13 16 21 17 18 19 20 22 35 23 28 24 25 26 27 29 34 30 31 32 33 6 7 8 9 1 0 1 1 1 2 1 3 1 4 1 5 1 6 1 7 1 8 1 9 2 0 2 1 2 2 3 5 2 3 2 8 2 4 2 5 2 6 2 7 2 9 3 4 3 0 3 2 3 1 3 3 3 6 PATH TO A NODE (breadcrumb) SELECT alias FROM #__ WHERE lft < 4 AND rgt > 5 ORDER BY lft ASC; #JAB14 - @EliAschkenasy ¨C Integral DB Design
  • 19. Root Node 1 2 3 4 5 lft rgt 1 36 2 15 3 8 4 5 6 7 9 14 10 11 12 13 16 21 17 18 19 20 22 35 23 28 24 25 26 27 29 34 30 31 32 33 6 7 8 9 1 0 1 1 1 2 1 3 1 4 1 5 1 6 1 7 1 8 1 9 2 0 2 1 2 2 3 5 2 3 2 8 2 4 2 5 2 6 2 7 2 9 3 4 3 0 3 2 3 1 3 3 3 6 PATH TO A NODE SELECT GROUP_CONCAT(alias SEPARATOR '/') as path FROM options WHERE lft <= 4 AND rgt >= 5 ORDER BY lft ASC; (sandal/blouse/skirt/woman) #JAB14 - @EliAschkenasy ¨C Integral DB Design
  • 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
  • 21. Root Node 1 2 3 4 5 lft rgt 1 36 2 15 3 8 4 5 6 7 9 14 10 11 12 13 16 21 17 18 19 20 22 35 23 28 24 25 26 27 29 34 30 31 32 33 6 7 8 9 1 0 1 1 1 2 1 3 1 4 1 5 1 6 1 7 1 8 1 9 2 0 2 1 2 2 3 5 2 3 2 8 2 4 2 5 2 6 2 7 2 9 3 4 3 0 3 2 3 1 3 3 3 6 #JAB14 - @EliAschkenasy ¨C Integral DB Design
  • 22. Root Node 1 2 3 4 5 lft rgt 1 36 2 15 3 8 4 5 6 7 9 14 10 11 12 13 16 21 17 18 19 20 22 35 23 28 24 25 26 27 29 34 30 31 32 33 6 7 8 9 1 0 1 1 1 2 1 3 1 4 1 5 1 6 1 7 1 8 1 9 2 0 2 1 2 2 3 5 2 3 2 8 2 4 2 5 2 6 2 7 2 9 3 4 3 0 3 2 3 1 3 3 3 6 LEVEL OF NODE SELECT b.id, COUNT(a.id) AS level FROM #__ AS a, #__ AS b WHERE b.lft BETWEEN a.lft AND a.rgt AND a.lft = 19 GROUP BY b.id #JAB14 - @EliAschkenasy ¨C Integral DB Design
  • 23. Root Node 1 2 3 4 5 lft rgt 1 36 2 15 3 8 4 5 6 7 9 14 10 11 12 13 16 21 17 18 19 20 22 35 23 28 24 25 26 27 29 34 30 31 32 33 6 7 8 9 1 0 1 1 1 2 1 3 1 4 1 5 1 6 1 7 1 8 1 9 2 0 2 1 2 2 3 5 2 3 2 8 2 4 2 5 2 6 2 7 2 9 3 4 3 0 3 2 3 1 3 3 3 6 #JAB14 - @EliAschkenasy ¨C Integral DB Design
  • 24. Root Node 1 2 3 4 5 lft rgt 1 36 2 15 3 8 4 5 6 7 9 14 10 11 12 13 16 21 17 18 19 20 22 35 23 28 24 25 26 27 29 34 30 31 32 33 6 7 8 9 1 0 1 1 1 2 1 3 1 4 1 5 1 6 1 7 1 8 1 9 2 0 2 1 2 2 3 5 2 3 2 8 2 4 2 5 2 6 2 7 2 9 3 4 3 0 3 2 3 1 3 3 3 6 PARENT ID OF A NODE SELECT id, (SELECT id FROM #__ t2 WHERE t2.lft < t1.lft AND t2.rgt > t1.rgt ORDER BY t2.rgt-t1.rgt ASC LIMIT 1) AS parentid FROM #__ t1 ORDER BY (rgt-lft) DESC #JAB14 - @EliAschkenasy ¨C Integral DB Design
  • 25. Root Node 1 2 3 4 5 lft rgt 1 36 2 15 3 8 4 5 6 7 9 14 10 11 12 13 16 21 17 18 19 20 22 35 23 28 24 25 26 27 29 34 30 31 32 33 6 7 8 9 1 0 1 1 1 2 1 3 1 4 1 5 1 6 1 7 1 8 1 9 2 0 2 1 2 2 3 5 2 3 2 8 2 4 2 5 2 6 2 7 2 9 3 4 3 0 3 2 3 1 3 3 3 6 MAXIMUM DEPTH SELECT MAX(level) AS height FROM ( SELECT b.id, (COUNT(a.id) - 1) AS level FROM #__ AS a, #__ AS b WHERE b.lft BETWEEN a.lft AND a.rgt GROUP BY b.id ) AS L1 #JAB14 - @EliAschkenasy ¨C Integral DB Design
  • 26. Root Node 1 2 3 4 5 lft rgt 1 36 2 15 3 8 4 5 6 7 9 14 10 11 12 13 16 21 17 18 19 20 22 35 23 28 24 25 26 27 29 34 30 31 32 33 6 7 8 9 1 0 1 1 1 2 1 3 1 4 1 5 1 6 1 7 1 8 1 9 2 0 2 1 2 2 3 5 2 3 2 8 2 4 2 5 2 6 2 7 2 9 3 4 3 0 3 2 3 1 3 3 3 6 INSERT A NODE UPDATE #__ SET rgt=rgt+2 WHERE rgt >= 25; UPDATE #__ SET lft=lft+2 WHERE lft >= 24; INSERT INTO #__ SET lft=24, rgt=25, ¡­.; #JAB14 - @EliAschkenasy ¨C Integral DB Design
  • 27. Root Node 1 2 3 4 5 lft rgt 1 36 2 15 3 8 4 5 6 7 9 14 10 11 12 13 16 21 17 18 19 20 22 35 23 28 24 25 26 27 29 34 30 31 32 33 6 7 8 9 1 0 1 1 1 2 1 3 1 4 1 5 1 6 1 7 1 8 1 9 2 0 2 1 2 2 3 5 2 3 2 8 2 4 2 5 2 6 2 7 2 9 3 4 3 0 3 2 3 1 3 3 3 6 INSERT A NODE UPDATE #__ SET rgt=rgt+2 WHERE rgt >= 25; UPDATE #__ SET lft=lft+2 WHERE lft >= 24; INSERT INTO #__ SET lft=24, rgt=25, ¡­.; #JAB14 - @EliAschkenasy ¨C Integral DB Design
  • 28. Root Node 1 2 3 4 5 lft rgt 1 36 2 15 3 8 4 5 6 7 9 14 10 11 12 13 16 21 17 18 19 20 22 35 23 28 24 25 26 27 29 34 30 31 32 33 6 7 8 9 1 0 1 1 1 2 1 3 1 4 1 5 1 6 1 7 1 8 1 9 2 0 2 1 2 2 3 7 2 3 3 0 2 6 2 7 2 8 2 9 3 1 3 6 3 2 3 4 3 3 3 5 3 8 INSERT A NODE UPDATE #__ SET rgt=rgt+2 WHERE rgt >= 25; UPDATE #__ SET lft=lft+2 WHERE lft >= 24; INSERT INTO #__ SET lft=24, rgt=25, ¡­.; 2 4 2 5 #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
  • 30. #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)
  • 46. #JAB14 - @EliAschkenasy ¨C Integral DB Design
  • 47. ? #JAB14 - @EliAschkenasy ¨C Integral DB Design
  • 48. ? ? #JAB14 - @EliAschkenasy ¨C Integral DB Design
  • 49. ? ? ? #JAB14 - @EliAschkenasy ¨C Integral DB Design
  • 50. ? ? ? ? #JAB14 - @EliAschkenasy ¨C Integral DB Design
  • 51. ? ? ? ? ? #JAB14 - @EliAschkenasy ¨C Integral DB Design
  • 52. ? ? ? ? ? ? #JAB14 - @EliAschkenasy ¨C Integral DB Design
  • 53. ? ? ? ? ? ? ? #JAB14 - @EliAschkenasy ¨C Integral DB Design
  • 54. #JAB14 - @EliAschkenasy ¨C Integral DB Design