2011-08-30 148 views
2

我试图创建一个规范化的数据库。正因为如此,我试图加入21个表格。我在联接的几乎所有表格上使用索引,如EXPLAIN声明的下面截图所示。慢Group_concat查询

http://i.imgur.com/V5hQu.png

所有lookup_xxxxx表对2列(CONTENT_ID和xxxxxx_id)一个索引 所有xxxxxx表具有1柱(xxxxx_id)

我只有大约10个左右的行中的一个索引每张表。我看到的问题是两个goup_concat延长了查询额外的200毫秒。我允许提交字段peripheralprogramming language具有多个值。没有他们,查询少于80毫秒。 我的问题是我是否应该废除group_concats并为它们执行单个查询或重建我的数据库。

lookup_xxxxx表存储每个允许的值,然后其他表(如peripheral)通过content_id将提交链接到允许的值。一切都参考了提交content_idcontent表持有必要的信息,如会员ID,名称等。

如果我的帖子不够清晰,我表示歉意。

mysql> describe peripheral; 
+------------------+----------+------+-----+---------+-------+ 
| Field   | Type  | Null | Key | Default | Extra | 
+------------------+----------+------+-----+---------+-------+ 
| peripheral_id | int(2) | NO | PRI | NULL |  | 
| peripheral  | char(30) | NO |  | NULL |  | 
| peripheral_total | int(5) | NO |  | NULL |  | 
+------------------+----------+------+-----+---------+-------+ 

mysql> select * from peripheral; 
+---------------+-----------------+------------------+ 
| peripheral_id | peripheral  | peripheral_total | 
+---------------+-----------------+------------------+ 
|    1 | periph 1  |    0 | 
|    2 | periph 2  |    1 | 
|    3 | periph 3  |    3 | 
+---------------+-----------------+------------------+ 

mysql> describe lookup_peripheral; 
+---------------+---------+------+-----+---------+-------+ 
| Field   | Type | Null | Key | Default | Extra | 
+---------------+---------+------+-----+---------+-------+ 
| content_id | int(10) | NO | MUL | NULL |  | 
| peripheral_id | int(2) | NO |  | NULL |  | 
+---------------+---------+------+-----+---------+-------+ 


mysql> mysql> select * from lookup_peripheral; 
+------------+---------------+ 
| content_id | peripheral_id | 
+------------+---------------+ 
|   74 |    2 | 
|   74 |    5 | 
|   75 |    2 | 
|   75 |    5 | 
|   76 |    3 | 
|   76 |    4 | 
+------------+---------------+ 

SELECT group_concat(DISTINCT peripheral.peripheral_id) as peripheral_id, group_concat(DISTINCT programming_language.programming_language_id) as programming_language_id, c.member_name, c.member_id, c.added_date_time, c.title, c.raw_summary, c.raw_all_content, c.meta_tags, c.main_pic_thumb, application.application_id, architecture.architecture_id, compiler.compiler_id, device_family.device_family_id, difficulty.difficulty_id, ide.ide_id, programmer.programmer_id, table_name.table_name_id, device_name.device_name 
FROM (content as c) 
INNER JOIN lookup_peripheral ON 76 = lookup_peripheral.content_id 
INNER JOIN peripheral ON peripheral.peripheral_id = lookup_peripheral.peripheral_id 
INNER JOIN lookup_programming_language ON 76 = lookup_programming_language.content_id 
INNER JOIN programming_language ON programming_language.programming_language_id = lookup_programming_language.programming_language_id 
....... 
LEFT OUTER JOIN device_name ON device_name.content_id = c.content_id 
INNER JOIN table_name ON table_name.table_name_id = lookup_table_name.table_name_id 
WHERE `c`.`content_id` = '76' 

回答

0

我想你也应该索引lookup_peripheral.peripheral_id领域。索引外键使得INNER JOIN更快。另外,你是否真的需要DISTINCT子句,因为你在连接ID字段? 关于第二个想法,也许你可以省略GROUP_CONCATs和内部联接(你的一些JOIN条件重叠,我相信,纠正我,如果我错了)

... (SELECT GROUP_CONCAT(l.peripheral_id) from lookup_peripheral lp where lp.content_id = 76) as peripheral_id, ... 

希望这有助于。