我有一个表格,它的行数不是很大(在 100ks 范围内),但包含大量原始数据,而且大小非常大。尽管行数相对较少,但大约为 1.5GB。
所以了解MySQL是将整行加载到内存中,还是只加载WHERE、ORDER BY和GROUP BY中使用的列和执行查询时的索引,以及最后的其余列是非常重要的?
查询示例:
SELECT HugeDataTable.*, Table2.Name
FROM Table1
LEFT JOIN Table2 ON Table1.`ID` = Table2.`Table1ID`
LEFT JOIN HugeDataTable FORCE INDEX(RowOrder) ON Table2.`ID` = HugeDataTable.`Table2ID`
WHERE HugeDataTable.Category = 5 AND Table1.ExampleColumn = integerExampleValue
AND HugeDataTable.RowOrder >10000 AND HugeDataTable.ID <> "h4324h534"
ORDER BY HugeDataTable.`RowOrder` DESC LIMIT 18 ;
使用 Explain SELECT 我设法发现 MySQL 每个查询扫描大约 70k 行。查询速度相当快,但我不确定这是否是行缓存的原因,因为我无法模拟服务器上的重负载。
所以,我的问题是,在查询将结果限制为 18 行后,是否会加载包含大量原始数据的列,从而最终只加载所需的少量原始数据?
或者它们会在限制之前加载,所以 70k 行,即大约 1GB 的数据值(value)在限制之前加载?如果是后一种情况,可以采取什么措施来防止这种情况发生,因为服务器只有 1GB 的 RAM。
编辑:我添加了 EXPLAIN。
id select_type table type possible_keys key key_len ref rows Extra
1 SIMPLE HugeDataTable range Table2ID,Category,RowOrder RowOrder 9 49591 Using where
1 SIMPLE Table2 eq_ref PRIMARY PRIMARY 10 const,HugeDataTable.Table2ID 1 Using where; Using index
1 SIMPLE Table1 ref PRIMARY PRIMARY 2 Table2.Table1ID 1
最佳答案
下次你问这样的问题时,你能不能包括 EXPLAIN 计划。
通常使用 LEFT JOIN,mysql 将在连接之前解析表之前的表之后(尽管并非总是如此)因此它将首先从表 1 读取行,然后是表 2,然后是 HugeDataTable。
但您的问题相当困惑 - 您不需要在查询输出中包含 WHERE、ORDER BY 和 GROUP BY 中的列。 SELECT * 绝不是一个好主意。唯一需要注意的是,如果您有多个查询所需列的组合,那么您将无法充分利用查询缓存。
但是这个查询在许多其他方面非常效率低下。为什么要按双左连接表中的值进行排序和限制?即使您的数据完整性完全崩溃,也有比这更好的解决方案。正如 aconrad 所说,您实现了一个非常昂贵的 INNER JOIN - 而不是此处的 LEFT JOIN。
强制索引通常是获得糟糕执行计划的好方法。
关于mysql - MySQL 是将整行加载到内存中,还是只加载 WHERE、ORDER BY 和 GROUP BY 中使用的列?,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/21118639/