这是我写的一个查询:
SELECT DISTINCT m.*, sm.*, s.*
FROM table_1 m
LEFT JOIN table_2 sm ON m.master_id = sm.master_id
INNER JOIN (
SELECT s1.*, rn.field1, d.field2, m.field3, dt.field4, gl.field5
FROM table_3 s1
LEFT JOIN table_4 rn ON s1.secondary_id = rn.secondary_id
LEFT JOIN table_5 d ON s1.trait_id = d.trait_id
LEFT JOIN table_6 m ON s1.mix_id = m.mix_id
LEFT JOIN table_7 dt ON s1.debit_id = dt.debit_id
LEFT JOIN table_8 gl ON s1.graph_id = gl.graph_id
WHERE s1.secondary_id = 26
AND s1.dimension_id = 24
AND s1.mix_id = 43
) s ON sm.spec_id = s.spec_id
WHERE m.master_id = 1
我正在一张非常小的桌子上测试它(每张桌子只有大约3000-5000条记录),并且从笔记本电脑上的虚拟机内获得可接受的结果(4.8毫秒)。
我的问题/问题是当表变大时,整个数据库不能驻留在内存中?
显然,所有* _id列都有索引(无论是s1表中的主键列还是外键。我在s1.secondary_id, s1.dimension_id, s1.mix_id
上都有一个多列索引。
这是否足够,或者是否比我更精通的人知道我是否应该使用不同的索引,或者完全使用不同的策略来进行这种查询(对表1的查询,对表2的连接,以及另一个连接反对子查询) - 这是让我暂停可伸缩性的最后一部分。
任何想法都表示赞赏。
PS - EXPLAIN
表示我可能正在使用临时表(我假设来自联接),但除此之外我不确定我在看什么,类型为const
,ref
,eq_ref
等
同样,它现在只需很少量的测试数据就能正常工作。一旦获得生产级别的数据,我就不希望它停止运转。
由于
答案 0 :(得分:3)
评论:
from
子句中的子查询可能会导致性能下降,因为它们通常都已实现。inner join
撤消left join
,因为on
子句要求密钥为非NULL
。table_3(secondary_id, dimension_id, mix_id)
上的索引(其他列可能在此之后有用)。答案 1 :(得分:0)
就像你提到的那样,你的查询将适用于较少数量的记录。 但是一旦你的数据库开始获得数百万(或数十万)的记录,你的查询就会变慢。
您可以在开始时采取预防措施,以便查询不会变慢:
将查询分成多个查询:这样您的数据库就会这样 也不会耗尽内存。
检查query execution plan 查看您的查询是否始终使用索引。它还会告诉您在各种连接操作中使用了多少时间。以及DB为优化您的查询而采取的步骤。
当数据被送入表中时,表和索引空间一直处于碎片状态。做常规去碎片
有一点可以肯定的是,Relational数据库不是为水平scaling而设计的,但是它们的垂直扩展非常好,因此安装额外的硬件(额外的内存,CPU)也有帮助
答案 2 :(得分:0)
LEFT
。s1
上有一个3列'复合'索引。EXPLAIN SELECT
以便我们更好地回答您的问题。我们需要看的不仅仅是它使用临时表。 也许 Explain将提供足够的信息来回答您的可扩展性问题。OPTIMIZE TABLE
;在InnoDB表上不值得努力。 BTree是自我整理(在某种程度上)。DISTINCT
(通常)需要临时表和数据的额外传递。由于您正在执行SELECT *
,因此您需要进行重复数据删除的唯一方法是在表中实际存在重复项。这似乎不太可能。varchar = numeric-constant
是唯一遇到麻烦的组合。常用的int = 'number'
可以优化OK。<强>解释强>
EXPLAINs
中的“行”列。它们都是小数字。