首页 > 解决方案 > Rails:如何在 rails 的非 id 列上创建聚集索引?

问题描述

我想将时间序列数据存储在数据库中。数据将按如下方式组织:

我正在尝试在 data_header_id 列而不是 id 列上创建具有聚集索引的表。这样我就可以通过简单的SELECT * FROM big_datums WHERE data_header_id = 9001 ORDER BY timestamp ASC.

我有以下代码,但由于 Rails 的默认设置而出错:

class CreateBigData < ActiveRecord::Migration[5.2]
  def up
    create_table :headers do |t|
      t.string :data_format
      t.timestamps
    end

    create_table :big_datums do |t|
      t.references :data_header, null: false # This will need to be a CLUSTED index
      t.integer :timestamp
      t.integer :point1
      t.integer :point2
    end

    execute "CREATE CLUSTERED INDEX [data-header-index] ON [dbo].[big_datums] ( [data_header_id] ASC )
             WITH (PAD_INDEX = OFF, STATISTICS_NORECOMPUTE = OFF, SORT_IN_TEMPDB = OFF, DROP_EXISTING = OFF,
             ONLINE = OFF, ALLOW_ROW_LOCKS = ON, ALLOW_PAGE_LOCKS = ON) ON [PRIMARY]"
    end
  end

  def down
    execute "DROP INDEX [data-header-index] ON [dbo].[big_datums] WITH ( ONLINE = OFF )"
    drop_table :big_datums
    drop_table :headers
  end
end

我收到此错误:

ActiveRecord::StatementInvalid: TinyTds::Error: 无法在表 'dbo.big_datums' 上创建多个聚集索引。在创建另一个之前删除现有的聚集索引 'PK__build_te__3213E83F6568EFB2'。

这似乎是因为 rails 已经为 id 提供了集群 PK。

问题:

1)如何按照描述创建表?

2)我还需要一个“id”列吗?我永远不会通过 ID 列进行查询,但是拥有一个 PK 列来唯一标识记录可能仍然很好——尤其是因为 header_id + timestamp 可能不是一个好的集群 PK

标签: sqlruby-on-railssql-server

解决方案


您已经有一个clustered indexon big_datums,只能clustered index在一个表上,因为它定义了数据的物理结构(数据如何存储等)。您可以创建一个非聚集索引来支持您的查询,或者只保留现有索引。您可以拥有许多它们,它们是聚集索引/堆的附加结构。

CREATE NONCLUSTERED INDEX [data-header-index] ON [dbo].[big_datums] ( [data_header_id] ASC )

最好在您的 . 中有一个唯一键clustered index,因为在其他情况下,sql server 会为您的 8kb 页面增加一些开销以使行唯一。


推荐阅读