2016-05-24 61 views
2

连接时速度很慢,我们有两个表:MySQL在复合键

SELECT B.x 
FROM B 
INNER JOIN A 
    ON A.b = B.b 
    AND A.c = B.c 
WHERE A.a IN (...a values...); 

a values从客户端语言给(我们的情况:红宝石)

create table A (
    id int, 
    a int, 
    b int, 
    c varchar(255), 
    unique key K1 (a,c), 
    key K2 (b,c), 
    key K3 (a,b,c) 
); 
create table B (
    id int, 
    b int, 
    c varchar(255), 
    x varchar(255), 
    unique key K (b,c) 
); 

像运行查询,以及有关10-100,000个项目。

解释是这样的。

*************************** 1. row *************************** 
      id: 1 
    select_type: SIMPLE 
     table: A 
     type: range 
      key: K 
     key_len: 4 
      ref: NULL 
     rows: 100 
     Extra: Using where; Using index 
*************************** 2. row *************************** 
      id: 1 
    select_type: SIMPLE 
     table: app_devices 
     type: ref 
      key: K 
     key_len: 4 
      ref: A.b 
     rows: 213 
     Extra: Using index condition 
2 rows in set (0.00 sec) 

当A和B很小时,这个查询很好用,但当表大小超过2000万行时,这个查询变得很慢。 我怀疑组合键在加入时工作不正常。我该如何解决这个问题?

+0

你应该阅读MySQL索引的[** ** TIPS(http://mysql.rjweb.org/doc.php/index_cookbook_mysql) –

+0

你的意思是'WHERE的AA(一...值...);'可以是100K的值?这对于索引搜索来说似乎并不理想。就像你加入'表A'和'Avalues'一样,但'Avalues'没有索引。你也没有A'(b,c)'的合成索引,所以你的连接'ON'没有使用正确的索引 –

+0

'(... a values ...)'实际上就是'(12,16,295,1053) '。 '(b,c)'存在,但我省略了,因为优化器没有使用它,对不起。我已编辑添加所有索引。 – mtomita

回答

1

C是一个VARCHAR(255)的索引,它在长度上相当大,并且还包含所有不包含数字的字符。如果VARCHAR的长度始终为255,则应将其设置为CHAR,以查看该展会的具体情况。

但是,如果您有2000万行,这意味着您的自动增量ID将只有8个长度,并且只会包含数字,这更适合您的连接。 把这个ID放在桌子上;

create table A (
    id int, 
    a int, 
    b int, 
    c varchar(255), 
    b_id int, //additional field 
    unique key K1 (a,c), 
    key K2 (b,c), 
    key K3 (a,b,c) 
); 
create table B (
    id int, 
    b int, 
    c varchar(255), 
    x varchar(255), 
    unique key K (b,c) 
); 

然后,一旦运行这个命令:

UPDATE a  
INNER JOIN B 
ON A.b = B.b 
AND A.c = B.c 
SET a.b_id = b.id 

然后将查询变为:

SELECT B.x 
FROM B 
INNER JOIN A 
ON A.b_id = b.id 
WHERE A.a IN (...a values...); 

这应该在一个合理的时间运行

编辑:

是您varchar(255)总是2 55长,还是可以更短?你可以缩短它。

如果您在不锁定的情况下将包含所有记录的表复制,并对副本执行添加自动增量更新,并且在短暂停机时间内(如果可能)将其重命名为原始数据库。

您可以使用以下问题来了解这是否适合您。 :

Surrogate vs. natural/business keys

+0

谢谢,我试了一下,并确认性能变好了,但是我们的编写器服务非常繁忙,所以添加自动增量id获取和更新可能会增加成本(因为A记录是在B之前创建的,所以A需要更新。出价)。让我想想... – mtomita