mysql integral db design #jab14

54
#JAB14 - @ EliAschkenasy Integral DB Design

Upload: eli-aschkenasy

Post on 28-Jan-2018

144 views

Category:

Software


4 download

TRANSCRIPT

#JAB14 - @EliAschkenasy – Integral DB Design

#JAB14 - @EliAschkenasy – Integral DB Design

• WHO AM I ?

#JAB14 - @EliAschkenasy – Integral DB Design

#JAB14 - @EliAschkenasy – Integral DB Design

#JAB14 - @EliAschkenasy – Integral DB Design

#JAB14 - @EliAschkenasy – Integral DB Design

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

10

11

12

13

14

15

16

17

18

19

20

21

22

35

23

28

24

25

26

27

29

34

30

32

31

33

36

#JAB14 - @EliAschkenasy – 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

10

11

12

13

14

15

16

17

18

19

20

21

22

35

23

28

24

25

26

27

29

34

30

32

31

33

36

ROOT NODE

root = lft == 1

#JAB14 - @EliAschkenasy – 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

10

11

12

13

14

15

16

17

18

19

20

21

22

35

23

28

24

25

26

27

29

34

30

32

31

33

36

TOTAL NODES

(rgt – lft + 1) / 2 = total

(36 – 1 + 1) / 2 = 18

#JAB14 - @EliAschkenasy – 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

10

11

12

13

14

15

16

17

18

19

20

21

22

35

23

28

24

25

26

27

29

34

30

32

31

33

36

IS LEAF NODE?

leaf = (rgt – lft ==1) ? true : false;

true = (5 – 4 == 1)

false = (8 – 3 == 1)

#JAB14 - @EliAschkenasy – 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

10

11

12

13

14

15

16

17

18

19

20

21

22

35

23

28

24

25

26

27

29

34

30

32

31

33

36

LEAF NODE OPTIMIZATIONOptimized implementation

SELECT x, x, xFROM #__WHERE lft = (rgt -1)

#JAB14 - @EliAschkenasy – 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

10

11

12

13

14

15

16

17

18

19

20

21

22

35

23

28

24

25

26

27

29

34

30

32

31

33

36

SUBTREE SELECTION OPTIMIZATION

SELECT c.type AS choices, b.type AS bottomFROM #__ AS c, #__ AS bWHERE c.lft BETWEEN b.lft AND b.rgt;

Anything between 22 and 35

#JAB14 - @EliAschkenasy – 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

10

11

12

13

14

15

16

17

18

19

20

21

22

35

23

28

24

25

26

27

29

34

30

32

31

33

36

SUBTREE SELECTION ONLY SUBTREEOptimized implementation

SELECT c.type AS choices, b.type AS bottomFROM #__ AS c, #__ AS bWHERE c.lft BETWEEN (b.lft+1) AND b.rgt;

Anyone between 23 and 35

#JAB14 - @EliAschkenasy – 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

10

11

12

13

14

15

16

17

18

19

20

21

22

35

23

28

24

25

26

27

29

34

30

32

31

33

36

#JAB14 - @EliAschkenasy – 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

10

11

12

13

14

15

16

17

18

19

20

21

22

35

23

28

24

25

26

27

29

34

30

32

31

33

36

#JAB14 - @EliAschkenasy – 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

10

11

12

13

14

15

16

17

18

19

20

21

22

35

23

28

24

25

26

27

29

34

30

32

31

33

36

PATH TO A NODE (breadcrumb)

SELECT aliasFROM #__WHERE lft < 4 AND rgt > 5ORDER BY lft ASC;

#JAB14 - @EliAschkenasy – 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

10

11

12

13

14

15

16

17

18

19

20

21

22

35

23

28

24

25

26

27

29

34

30

32

31

33

36

PATH TO A NODE

SELECT GROUP_CONCAT(alias SEPARATOR '/') as pathFROM optionsWHERE lft <= 4 AND rgt >= 5ORDER BY lft ASC;(sandal/blouse/skirt/woman)

#JAB14 - @EliAschkenasy – Integral DB Design

PATH TO A NODE

SELECT GROUP_CONCAT(alias SEPARATOR '/') as pathFROM con_menuWHERE lft <= 20 AND rgt >= 21 AND lft > 1ORDER BY lft ASC;(Messaging/Read Private Message)

#JAB14 - @EliAschkenasy – 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

10

11

12

13

14

15

16

17

18

19

20

21

22

35

23

28

24

25

26

27

29

34

30

32

31

33

36

#JAB14 - @EliAschkenasy – 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

10

11

12

13

14

15

16

17

18

19

20

21

22

35

23

28

24

25

26

27

29

34

30

32

31

33

36

LEVEL OF NODE

SELECT b.id, COUNT(a.id) AS levelFROM #__ AS a, #__ AS bWHERE b.lft BETWEEN a.lft AND a.rgtAND a.lft = 19GROUP BY b.id

#JAB14 - @EliAschkenasy – 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

10

11

12

13

14

15

16

17

18

19

20

21

22

35

23

28

24

25

26

27

29

34

30

32

31

33

36

#JAB14 - @EliAschkenasy – 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

10

11

12

13

14

15

16

17

18

19

20

21

22

35

23

28

24

25

26

27

29

34

30

32

31

33

36

PARENT ID OF A NODE

SELECT id, (SELECT idFROM #__ t2 WHERE t2.lft < t1.lft AND t2.rgt > t1.rgt ORDER BY t2.rgt-t1.rgt ASCLIMIT 1)

AS parentid FROM #__ t1 ORDER BY (rgt-lft) DESC

#JAB14 - @EliAschkenasy – 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

10

11

12

13

14

15

16

17

18

19

20

21

22

35

23

28

24

25

26

27

29

34

30

32

31

33

36

MAXIMUM DEPTH

SELECT MAX(level) AS heightFROM (

SELECT b.id, (COUNT(a.id) - 1) AS levelFROM #__ AS a, #__ AS bWHERE b.lft BETWEEN a.lft AND a.rgtGROUP BY b.id) AS L1

#JAB14 - @EliAschkenasy – 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

10

11

12

13

14

15

16

17

18

19

20

21

22

35

23

28

24

25

26

27

29

34

30

32

31

33

36

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 – 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

10

11

12

13

14

15

16

17

18

19

20

21

22

35

23

28

24

25

26

27

29

34

30

32

31

33

36

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 – 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

10

11

12

13

14

15

16

17

18

19

20

21

22

37

23

30

26

27

28

29

31

36

32

34

33

35

38

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, ….;

24

25

#JAB14 - @EliAschkenasy – Integral DB Design

• WHO AM I ?

• NESTED SET INTRO

• NESTED SET BASIC QUERIES

• NESTED SET BASIC QUERIES OPTIMIZATION

#JAB14 - @EliAschkenasy – Integral DB Design

#JAB14 - @EliAschkenasy – 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 – 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. Speed2. Data accuracy (inconsistent white spacing)

#JAB14 - @EliAschkenasy – 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. Speed2. Data accuracy (inconsistent white spacing)

#JAB14 - @EliAschkenasy – 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 = $crcAND part_number_concat = $concat; (singularity)

PROBLEMS:

1. Speed2. Data accuracy (inconsistent white spacing)

#JAB14 - @EliAschkenasy – 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 = $crcAND part_number_concat = $concat; (singularity)

PROBLEMS:

1. Speed2. Data accuracy (inconsistent 32bit vs 64bit)

#JAB14 - @EliAschkenasy – 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. Speed2. Data accuracy (inconsistent 32bit vs 64bit)

#JAB14 - @EliAschkenasy – Integral DB Design

Optimized INSERT (* BATCH)

php: $concat = preg_replace('/\s+/', '', $input);

ALTER TABLE #__ DROP INDEX xINSERT INTO #__ (part_number, unit_price, eau,part_number_concat,sha_partnumberconcat…)VALUES (…,$concat concat,SHA1($concat));ALTER TABLE #__ ADD INDEX x (‘column’)

#JAB14 - @EliAschkenasy – 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 – 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 – 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 + 1WHERE 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 – Integral DB Design

#JAB14 - @EliAschkenasy – Integral DB Design

SELECT * FROM Orgchart SELECT a, c FROM Orgchart SELECT a, c FROM OrgchartWHERE lft - rgt = 1; WHERE lft - rgt = 1; WHERE lft =(rgt – 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 – Integral DB Design

SELECT * FROM Orgchart SELECT a, c FROM Orgchart SELECT a, c FROM OrgchartWHERE lft - rgt = 1; WHERE lft - rgt = 1; WHERE lft =(rgt – 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 payment\G*************************** 1. row ***************************SUM(staff_id = 2): 7992SUM(customer_id = 584): 30ALTER TABLE payment ADD KEY(customer_id, staff_id);

#JAB14 - @EliAschkenasy – 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 – 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 25ORDER BY rating ASCMySQL 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 – 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 queryTrick: Convert WHERE age BETWEEN 18 and 25 toWHERE age IN(18,19,20,21,22,23,24,25)

#JAB14 - @EliAschkenasy – Integral DB Design

#JAB14 - @EliAschkenasy – Integral DB Design

#JAB14 - @EliAschkenasy – Integral DB Design

#JAB14 - @EliAschkenasy – Integral DB Design

#JAB14 - @EliAschkenasy – Integral DB Design

#JAB14 - @EliAschkenasy – Integral DB Design

#JAB14 - @EliAschkenasy – Integral DB Design

#JAB14 - @EliAschkenasy – Integral DB Design

#JAB14 - @EliAschkenasy – Integral DB Design