0

我有一个超过 1100 万行的大型 MySql 表。这只是一个庞大的数据集,我的任务是能够根据某些规则分析数据集。

每一行都属于某一个category。有 200 万个不同的类别。我想获取一个类别的所有行并对其执行操作。

因此,目前,我执行以下操作:

  1. 从表中选择不同的类别。
  2. 对于每个类别:从表中选择字段 WHERE category=category

即使我的category列已编入索引,执行也需要很长时间Step 2。这主要是因为庞大的数据集。

或者,我可以使用 GROUP BY 子句,但是我不确定它是否会一样快,因为在如此庞大的数据集上使用 GROUP BY 可能会很昂贵,尤其是考虑到我将在部分数据集上运行多次分析时。一种永久确保排序表的方法会很有用。

因此,作为替代方案,如果只有我的表预先排序,我可以加快查询速度category。现在我可以逐行读取表格并在更快的时间内执行相同的操作,因为一个行的所有行都category将被连续获取。

由于数据集(MySql 表)是固定的,不会对其进行更新、删除、插入操作。我希望能够确保一种方法来维护默认排序顺序category。任何人都可以提出一个技巧来确保行的默认排序顺序。

也许读取所有行并将它们重写到一个新表或添加一个新的主键来确保这个顺序?

4

2 回答 2

0

即使我的类别列已编入索引

二级索引索引?如果是这样,您可能会遇到以下性能问题:

  • InnoDB 表始终是聚集的,并且聚集表中的二级索引可能需要双重查找(请参阅本文中的“集群的缺点” )。
  • 索引行可能分散在各处(索引可能具有不良的聚集因子- 链接适用于 Oracle,但原理相同)。如果是这样,索引范围扫描(例如WHERE category = whatever)最终可能会加载许多表页,即使实际使用了索引并且实际上只选择了一小部分行。这会破坏范围扫描性能。

作为二级索引的替代方案,考虑使用自然主键,它在 InnoDB 表中也充当集群键。主键/集群键{category, no}将保持同一类别的行物理上靠近在一起,使您的两个查询(尤其是第二个)最大效率。

OTOH,如果您想保留二级索引,请考虑覆盖您查询的所有字段,因此根本不必触及主 B-Tree。

于 2013-01-13T16:39:09.890 回答
0

无论索引如何,您都可以通过执行以下操作(伪代码)一步完成此操作:

Declare @LastCategory int = Null
Declare @Category int

For Each Row In
Select
  @Category = Category,
  ...
From
  Table
Order By 
  Category

  If @LastCategory Is Null Or @LastCategory != @Category
    Do any "New Category Steps"
    Set @LastCategory = @Category
  End
  Process Row

End For

使用类别索引,我希望这可以执行。您的性能问题可能取决于您在处理每一行时所做的事情。

这是一个例子:http ://sqlfiddle.com/#!2/e53c98/1

于 2013-01-13T16:40:36.570 回答