我有多个表,我试图加入。我已经为表添加了索引以提高速度,但仍然需要很长时间才能加入。我怀疑这是预期的,但我想知道是否有更有效的方法来创建多个表的连接。我还将net_read_timeout =设置为150,因为我收到了丢失的连接错误。我的查询如下:
set net_read_timeout = 150;
ALTER TABLE wspeed2 ADD INDEX (speed,roadtypeID) --For all the tables
SELECT a.month,a.roadTypeID,a.speed,a.pid, a.or, b.pid, b.or, c.pid, c.or, d.pid, d.or,
e.pid, e.or, f.pid, f.or, g.pid, g.or, h.pid, h.or, i.pid, i.or, j.pid, j.or,
k.pid, k.or, l.pid, l.or, m.pid, m.or, n.pid, n.or, o.pid, o.or, p.pid, p.or,
q.pid, q.or, r.pid, r.or, s.pid, s.or, t.pid, t.or, u.pid, u.or, v.pid, v.or
FROM wspeed2 a, wspeed3 b, wspeed20 c, wspeed24 d, wspeed25 e, wspeed26 f, wspeed27 g, wspeed63 h, wspeed65 i, wspeed68 j,
wspeed69 k, wspeed70 l, wspeed71 m, wspeed72 n, wspeed73 o, wspeed74 p, wspeed75 q, wspeed76 r, wspeed77 s, wspeed78 t, wspeed81 u, wspeed82 v
WHERE a.speed = b.speed and b.speed = c.speed and c.speed = d.speed and d.speed = e.speed and e.speed = f.speed and f.speed = g.speed and g.speed = h.speed
and h.speed = i.speed and i.speed = j.speed and j.speed = k.speed and k.speed = l.speed and l.speed = m.speed and m.speed = n.speed and n.speed = o.speed
and o.speed = p.speed and p.speed = q.speed and q.speed = r.speed and r.speed = s.speed and s.speed = t.speed and t.speed = u.speed and u.speed = v.speed
GROUP BY a.speed;
答案 0 :(得分:0)
使用内部和左/右连接将为您提供更好的性能。尝试以这种方式重写查询 -
select ... from t1
innerjoin t2 on t1.pk=t2.fk
leftjoin t3 on t1.pk=t3.fk
答案 1 :(得分:0)
虽然查询本身看起来很简单但很奇怪,但这里有连接。注意......因为你有一个= bb = cc = d等...它也意味着a = ra = sa = t等...所以,不是所有人都依赖于它前面的别名,它可能会帮助将所有其他速度表直接连接到根“a”级别别的引擎,如下所示。
也就是说,您正在加入21个不同的表,如果一个或多个表没有“a”表中相应速度的记录,它们将不会出现在结果集中。如果您想要ALL而不管其他表中是否匹配,请将它们全部更改为LEFT JOIN。
现在,查看“a”表,您将根据道路类型和每个月的速度来确定。速度列是一个独特的列吗?我认为是,但不是积极的。如果要连接的任何基础表每个相同的速度值具有多于1个记录,您将获得笛卡尔结果并且可能会阻塞您的查询。
此外,你有一个group by,但是没有聚合函数列,例如SUM(某事),count(),avg(),min(),max(),那么分组的重点是什么。你可能希望它按某种东西排序(最好是“a”表上有索引的东西。
SELECT
a.month, a.roadTypeID, a.speed,
a.pid, a.or, b.pid, b.or, c.pid, c.or, d.pid, d.or,
e.pid, e.or, f.pid, f.or, g.pid, g.or, h.pid, h.or,
i.pid, i.or, j.pid, j.or, k.pid, k.or, l.pid, l.or,
m.pid, m.or, n.pid, n.or, o.pid, o.or, p.pid, p.or,
q.pid, q.or, r.pid, r.or, s.pid, s.or, t.pid, t.or,
u.pid, u.or, v.pid, v.or
FROM
wspeed2 a
JOIN wspeed3 b on a.speed = b.speed
JOIN wspeed20 c on a.speed = c.speed
JOIN wspeed24 d on a.speed = d.speed
JOIN wspeed25 e on a.speed = e.speed
JOIN wspeed26 f on a.speed = f.speed
JOIN wspeed27 g on a.speed = g.speed
JOIN wspeed63 h on a.speed = h.speed
JOIN wspeed65 i on a.speed = i.speed
JOIN wspeed68 j on a.speed = j.speed
JOIN wspeed69 k on a.speed = k.speed
JOIN wspeed70 l on a.speed = l.speed
JOIN wspeed71 m on a.speed = m.speed
JOIN wspeed72 n on a.speed = n.speed
JOIN wspeed73 o on a.speed = o.speed
JOIN wspeed74 p on a.speed = p.speed
JOIN wspeed75 q on a.speed = q.speed
JOIN wspeed76 r on a.speed = r.speed
JOIN wspeed77 s on a.speed = s.speed
JOIN wspeed78 t on a.speed = t.speed
JOIN wspeed81 u on a.speed = u.speed
JOIN wspeed82 v on a.speed = v.speed
如果仍然没有帮助,可能会添加MySQL关键字“STRAIGHT_JOIN”,例如:
选择STRAIGHT_JOIN [其余查询]
答案 2 :(得分:0)
如果speed
列在这些表中不是唯一的(可能不是;假设您说您添加了一个以speed
作为前导列的索引...
如果有多个行具有相同的speed
值,则在这些表中,您的查询可能会创建一个巨大的中间集。
让我们做一些简单的数学运算。如果每个表中有两行具有相同的速度值,则a和b之间的JOIN操作将为该速度创建4行。当我们将连接添加到c时,另外两行,即总共8行。当我们加入所有22个表时,每个表有两行,我们处于2 ^ 22或超过400万行。然后,需要在GROUP BY操作中处理具有speed
的所有相同值的整个行集,以消除重复。
(当然,如果其中任何一个表没有相同speed
值的行,那么查询将为speed
生成零行。)
就个人而言,我会抛弃JOIN操作的旧式逗号语法,而是使用JOIN关键字。我将连接谓词从WHERE子句移动到适当的ON子句。
我还将其中一个表作为所有连接的“驱动程序”,我将在每个连接中使用对同一个表的引用。 (我们知道,如果a=b
和b=c
,那么a=c
。但我不确定MySQL优化器,我们是否指定a=b and a=c
是否有任何区别a=b and b=c
。
如果每个表中speed
的不同值的数量相对较少,但是有很多行具有相同的值,我会考虑使用内联视图从每个表中为每个速度获取一行的表格。 MySQL可以使用合适的索引来优化每个表上的GROUP BY操作......我会选择覆盖索引......例如。
ON wspeed20 (speed, pid, `or`)
ON wspeed24 (speed, pid, `or`)
不幸的是,派生表(内联视图查询的结果)没有编入索引,因此JOIN操作可能很昂贵(对于每个内联视图查询中的很多行)。
SELECT a.month,a.roadTypeID,a.speed,a.pid,a.or, b.pid, b.or, c.pid, c.or, d.pid, d.or,
e.pid, e.or, f.pid, f.or, g.pid, g.or, h.pid, h.or, i.pid, i.or, j.pid, j.or,
k.pid, k.or, l.pid, l.or, m.pid, m.or, n.pid, n.or, o.pid, o.or, p.pid, p.or,
q.pid, q.or, r.pid, r.or, s.pid, s.or, t.pid, t.or, u.pid, u.or, v.pid, v.or
FROM (SELECT speed, pid, `or` FROM wspeed2 GROUP BY speed) a
JOIN (SELECT speed, pid, `or` FROM wspeed3 GROUP BY speed) b ON b.speed = a.speed
JOIN (SELECT speed, pid, `or` FROM wspeed20 GROUP BY speed) c ON c.speed = a.speed
JOIN (SELECT speed, pid, `or` FROM wspeed24 GROUP BY speed) d ON d.speed = a.speed
JOIN (SELECT speed, pid, `or` FROM wspeed25 GROUP BY speed) e ON e.speed = a.speed
JOIN (SELECT speed, pid, `or` FROM wspeed26 GROUP BY speed) f ON f.speed = a.speed
JOIN (SELECT speed, pid, `or` FROM wspeed27 GROUP BY speed) g ON g.speed = a.speed
JOIN (SELECT speed, pid, `or` FROM wspeed63 GROUP BY speed) h ON h.speed = a.speed
JOIN (SELECT speed, pid, `or` FROM wspeed65 GROUP BY speed) i ON i.speed = a.speed
JOIN (SELECT speed, pid, `or` FROM wspeed68 GROUP BY speed) j ON j.speed = a.speed
JOIN (SELECT speed, pid, `or` FROM wspeed69 GROUP BY speed) k ON k.speed = a.speed
JOIN (SELECT speed, pid, `or` FROM wspeed70 GROUP BY speed) l ON l.speed = a.speed
JOIN (SELECT speed, pid, `or` FROM wspeed71 GROUP BY speed) m ON m.speed = a.speed
JOIN (SELECT speed, pid, `or` FROM wspeed72 GROUP BY speed) n ON n.speed = a.speed
JOIN (SELECT speed, pid, `or` FROM wspeed73 GROUP BY speed) o ON o.speed = a.speed
JOIN (SELECT speed, pid, `or` FROM wspeed74 GROUP BY speed) p ON p.speed = a.speed
JOIN (SELECT speed, pid, `or` FROM wspeed75 GROUP BY speed) q ON q.speed = a.speed
JOIN (SELECT speed, pid, `or` FROM wspeed76 GROUP BY speed) r ON r.speed = a.speed
JOIN (SELECT speed, pid, `or` FROM wspeed77 GROUP BY speed) s ON s.speed = a.speed
JOIN (SELECT speed, pid, `or` FROM wspeed78 GROUP BY speed) t ON t.speed = a.speed
JOIN (SELECT speed, pid, `or` FROM wspeed81 GROUP BY speed) u ON u.speed = a.speed
JOIN (SELECT speed, pid, `or` FROM wspeed82 GROUP BY speed) v ON v.speed = a.speed
这有可能减少需要加入的行数(同样,如果speed
存在大量重复值,并且{{1}有少量不同值但是,再次,派生表之间的JOIN操作将没有任何可用的索引。 (至少,不是MySQL版本高达5.6。)