确保MySql表中的某些默认排序顺序

时间:2013-01-13 16:13:33

标签: mysql sql database-design

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

每一行都属于某个category。有200万个不同的类别。我希望得到一个类别的所有行并对其执行操作。

目前,我做了以下事情:

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

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

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

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

    由于数据集(MySql表)已修复且无更新,删除,因此将对其执行插入操作。我希望能够确保按category维护默认排序顺序的方法。任何人都可以建议一个技巧,以确保行的默认排序顺序。

    也许读取所有行并将它们重写为新表或添加新的主键以确保此顺序?

2 个答案:

答案 0 :(得分:0)

  

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

使用次要索引编制索引?如果是这样,您可能会遇到以下性能问题:

  • InnoDB表始终为clustered,群集表中的二级索引可能需要双重查找(请参阅this article中的“群集的缺点”)。
  • 索引行可以遍布整个地方(索引可能有错误clustering factor - 该链接适用于Oracle,但原理相同)。如果是这样,索引范围扫描(例如WHERE category = whatever)可以最终加载许多表页,即使实际使用了索引并且实际上只选择了一小部分行。这可能会破坏范围扫描性能。

除了二级索引之外,请考虑使用自然主键,InnoDB表中的自然主键也可用作聚类键。主要/群集密钥(例如{category, no})将使相同类别的行保持物理上靠近,从而使您的两个查询(尤其是第二个)最大限度地提高效率。

OTOH,如果你想保留二级索引,可以考虑covering你查询的所有字段,这样就不必触及主B树。

答案 1 :(得分: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