2012-07-12 65 views
1

我有一个让他们之间的外键约束连接表:MySQL的性能

Table event 
mysql> describe event; 
+------------+------------------+------+-----+---------+-------+ 
| Field  | Type    | Null | Key | Default | Extra | 
+------------+------------------+------+-----+---------+-------+ 
| sid  | int(10) unsigned | NO | PRI | NULL |  | 
| cid  | int(10) unsigned | NO | PRI | NULL |  | 
| signature | int(10) unsigned | NO | MUL | NULL |  | 
| timestamp | datetime   | NO | MUL | NULL |  | 
| is_deleted | tinyint(1)  | NO | MUL | 0  |  | 
+------------+------------------+------+-----+---------+-------+ 
5 rows in set (0.00 sec) 

Table signature 
mysql> describe signature; 
+--------------+------------------+------+-----+---------+----------------+ 
| Field  | Type    | Null | Key | Default | Extra   | 
+--------------+------------------+------+-----+---------+----------------+ 
| sig_id  | int(10) unsigned | NO | PRI | NULL | auto_increment | 
| sig_name  | varchar(255)  | NO | MUL | NULL |    | 
| sig_class_id | int(10) unsigned | NO | MUL | NULL |    | 
| sig_priority | int(10) unsigned | YES |  | NULL |    | 
| sig_rev  | int(10) unsigned | YES |  | NULL |    | 
| sig_sid  | int(10) unsigned | YES |  | NULL |    | 
| sig_gid  | int(10) unsigned | YES |  | NULL |    | 
+--------------+------------------+------+-----+---------+----------------+ 
7 rows in set (0.00 sec) 

event.signature是一个外键和链接到signature.sig_id两个表。两者都有指标以及

表事件是大的(比如说1M记录),而表签名会比较小(几千元最多)

访问任何签字注册查询属性需要很长的时间来执行。一看解释

mysql> explain select event.sid,event.cid,signature.sig_name from event join signature on signature.sig_id=event.signature; 
+----+-------------+-----------+------+--------------------------------+-----------------------+---------+-------------------------+------+--------------------------+ 
| id | select_type | table  | type | possible_keys     | key     | key_len | ref      | rows | Extra     | 
+----+-------------+-----------+------+--------------------------------+-----------------------+---------+-------------------------+------+--------------------------+ 
| 1 | SIMPLE  | signature | ALL | PRIMARY,index_signature_sig_id | NULL     | NULL | NULL     | 127 |       | 
| 1 | SIMPLE  | event  | ref | index_event_signature   | index_event_signature | 5  | snorby.signature.sig_id | 68 | Using where; Using index | 
+----+-------------+-----------+------+--------------------------------+-----------------------+---------+-------------------------+------+--------------------------+ 
2 rows in set (0.00 sec) 

虽然如果没有签名属性被访问

如果签名属性查询它完全扫描ALL
mysql> explain select event.sid,event.cid from event join signature on signature.sig_id=event.signature; 
+----+-------------+-----------+-------+--------------------------------+------------------------+---------+-------------------------+------+--------------------------+ 
| id | select_type | table  | type | possible_keys     | key     | key_len | ref      | rows | Extra     | 
+----+-------------+-----------+-------+--------------------------------+------------------------+---------+-------------------------+------+--------------------------+ 
| 1 | SIMPLE  | signature | index | PRIMARY,index_signature_sig_id | index_signature_sig_id | 4  | NULL     | 127 | Using index    | 
| 1 | SIMPLE  | event  | ref | index_event_signature   | index_event_signature | 5  | snorby.signature.sig_id | 68 | Using where; Using index | 
+----+-------------+-----------+-------+--------------------------------+------------------------+---------+-------------------------+------+--------------------------+ 
2 rows in set (0.00 sec) 

可以看出连接类型。

是否有可能重写查询更快?我问这个,因为这是多个表的一部分加入,与签名加入事件是减缓查询极大

的瓶颈,我用52年5月1日MySQL和SQLAlchemy的0.7.8作为ORM

回答

1

你查询确实按定义需要全面扫描。

也就是说,你没有给出过滤条件。例如,没有... WHERE sig_rev = 17

因此,这里没有多少改进。 MySQL选择一个表开始,进行全面扫描,每行读取第二个表中的匹配行。

所以扫描是必不可少的。但是你可以把它变成索引扫描而不是表扫描。我假设您只有signature列和仅有sig_id列的索引。

你可以做的是对sig_id, sig_name创建一个额外的指标,如:

ALTER TABLE signature ADD UNIQUE INDEX(sig_id, sig_name); 

该指数是通过定义独一无二的,因为它比PRIMARY KEY更广泛的,但这是一点之外。

您现在可能获得的执行计划类似于您发布的第二个示例:在signature上进行索引扫描,然后是对事件的索引查找。

确保比较并验证您是否在此特定查询上获得了性能提升。检查新索引是否损坏INSERT性能等。

祝你好运。

+0

我曾经这么认为......但即使在sig_id上添加唯一索引,sig_name(255)也不会更改执行计划。它在使用的密钥中仍然是NULL。我想我必须重写代码并确保获得所有其他属性,然后仅查询签名以获取特定的签名标识 – RedBaron 2012-07-12 11:28:32

+0

然后,MySQL可能不会批准使用索引,因为您的表可能不够大。 在查询中尝试'FORCE INDEX(the_new_index_name)'... – 2012-07-12 12:06:55

+0

其实问题是我在订购基于非索引列的查询。但我忘了提及它。 – RedBaron 2012-07-13 05:49:49