Đây là một ví dụ đơn giản mà tôi đã làm cho một câu hỏi liên quan đến hiệu suất tương tự cách đây một lúc, tận dụng các chỉ mục khóa chính cụm innodb (rõ ràng là chỉ khả dụng với innodb !!)
- http://dev.mysql. com / doc / refman / 5.0 / en / innodb-index-styles.html
- http:/ /www.xaprb.com/blog/2006/07/04/how-to-exploit-mysql-index-optimizations/
Bạn có 3 bảng:category, product và product_category như sau:
drop table if exists product;
create table product
(
prod_id int unsigned not null auto_increment primary key,
name varchar(255) not null unique
)
engine = innodb;
drop table if exists category;
create table category
(
cat_id mediumint unsigned not null auto_increment primary key,
name varchar(255) not null unique
)
engine = innodb;
drop table if exists product_category;
create table product_category
(
cat_id mediumint unsigned not null,
prod_id int unsigned not null,
primary key (cat_id, prod_id) -- **note the clustered composite index** !!
)
engine = innodb;
Thứ nhập nhiều nhất là thứ tự của khóa chính tổng hợp nhóm product_catgeory như các truy vấn điển hình cho trường hợp này luôn dẫn đầu bởi cat_id =x hoặc cat_id in (x, y, z ...).
Chúng tôi có 500 nghìn danh mục, 1 triệu sản phẩm và 125 triệu danh mục sản phẩm.
select count(*) from category;
+----------+
| count(*) |
+----------+
| 500000 |
+----------+
select count(*) from product;
+----------+
| count(*) |
+----------+
| 1000000 |
+----------+
select count(*) from product_category;
+-----------+
| count(*) |
+-----------+
| 125611877 |
+-----------+
Vì vậy, hãy xem lược đồ này hoạt động như thế nào đối với một truy vấn tương tự như của bạn. Tất cả các truy vấn đều chạy nguội (sau khi khởi động lại mysql) với bộ đệm trống và không có bộ nhớ đệm truy vấn.
select
p.*
from
product p
inner join product_category pc on
pc.cat_id = 4104 and pc.prod_id = p.prod_id
order by
p.prod_id desc -- sry dont a date field in this sample table - wont make any difference though
limit 20;
+---------+----------------+
| prod_id | name |
+---------+----------------+
| 993561 | Product 993561 |
| 991215 | Product 991215 |
| 989222 | Product 989222 |
| 986589 | Product 986589 |
| 983593 | Product 983593 |
| 982507 | Product 982507 |
| 981505 | Product 981505 |
| 981320 | Product 981320 |
| 978576 | Product 978576 |
| 973428 | Product 973428 |
| 959384 | Product 959384 |
| 954829 | Product 954829 |
| 953369 | Product 953369 |
| 951891 | Product 951891 |
| 949413 | Product 949413 |
| 947855 | Product 947855 |
| 947080 | Product 947080 |
| 945115 | Product 945115 |
| 943833 | Product 943833 |
| 942309 | Product 942309 |
+---------+----------------+
20 rows in set (0.70 sec)
explain
select
p.*
from
product p
inner join product_category pc on
pc.cat_id = 4104 and pc.prod_id = p.prod_id
order by
p.prod_id desc -- sry dont a date field in this sample table - wont make any diference though
limit 20;
+----+-------------+-------+--------+---------------+---------+---------+------------------+------+----------------------------------------------+
| id | select_type | table | type | possible_keys | key | key_len | ref | rows | Extra |
+----+-------------+-------+--------+---------------+---------+---------+------------------+------+----------------------------------------------+
| 1 | SIMPLE | pc | ref | PRIMARY | PRIMARY | 3 | const | 499 | Using index; Using temporary; Using filesort |
| 1 | SIMPLE | p | eq_ref | PRIMARY | PRIMARY | 4 | vl_db.pc.prod_id | 1 | |
+----+-------------+-------+--------+---------------+---------+---------+------------------+------+----------------------------------------------+
2 rows in set (0.00 sec)
Vì vậy, đó là 0,70 giây lạnh - ouch.
Hy vọng điều này sẽ giúp :)
CHỈNH SỬA
Vừa đọc câu trả lời của bạn cho nhận xét của tôi ở trên, có vẻ như bạn có một trong hai lựa chọn để thực hiện:
create table articles_to_categories
(
article_id int unsigned not null,
category_id mediumint unsigned not null,
primary key(article_id, category_id), -- good for queries that lead with article_id = x
key (category_id)
)
engine=innodb;
hoặc.
create table categories_to_articles
(
article_id int unsigned not null,
category_id mediumint unsigned not null,
primary key(category_id, article_id), -- good for queries that lead with category_id = x
key (article_id)
)
engine=innodb;
phụ thuộc vào điển hình của bạn truy vấn về cách bạn xác định PK nhóm của mình.