我们有两张桌子:
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)
);
运行以下查询:
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
来自客户端语言(我们的案例:Ruby),以及大约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 :(得分: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)的长度总是255,还是可以短得多?你可以缩短它。
如果您在没有锁定的情况下复制包含所有记录的表,并在副本上执行添加自动增量更新,并在短暂的停机时间内(如果可能)将其重命名为原始数据库。
您可以使用以下问题来确定这是否适合您。 :