1

我正在尝试提高多租户 SaaS 系统上大型表的性能,以使报告更快。当我在聚集索引上添加一列时,在系统上进行插入操作的时间从 ~30ms 增加到 1500~2500ms!在这种情况下,应用于此表的最佳聚集索引选项和非聚集索引是什么:

  • 数据库:SQL Azure
  • 我只在这个表上执行 INSERT 和 SELECT,数据从不更新(UPDATE)
  • 并发 INSERTS 的高负载(不同的 Worker 和线程消耗队列中的数据)
  • 100.000 行/天(增长)
  • 实际上 600 万行(增长)
  • 每个租户只读取其 ID 的数据
  • 1 个租户将拥有 100-3000 个 DeviceId

表结构:
-TenantID (bigint)(我可以使用 smallint,但如果我将来需要使用 Azure 联合,我更改为 bigint )-DeviceID
(int)
- ReadID (bigint) (Identity)
- UIDRead (GUID)
- ReadDate (日期时间)
- SensorState1 (tinyint)
- SensorState2 (tinyint)
- SensorState3 (tinyint)
...
- SensorState10 (tinyint)

常见的 WHERE 用于读取数据:
-WHERE DeviceId = @X and ReadDate between @XDate and @YDate
-WHERE DeviceId IN (X,Y,Z) AND ReadDate between @XDate and @YDate
-WHERE TenantId = @Y and ReadDate在@XDate 和@YDate
之间 -WHERE TenantId = @X AND DeviceID IN (X,Y,Z) AND ReadDate 在@XDate 和@YDate 之间 -WHERE
TenantId = @X AND DeviceID =@Y AND ReadDate 在@XDate 和@YDate 之间

4

1 回答 1

1

什么是主键?我假设ReadDate,TenantIdDeviceId构成唯一标识符?如果是这样,通过在表定义中声明主键,按顺序对它们进行聚类。始终将日期放在时间序列数据的聚集索引的前面,因为范围是连续的。(是的,我知道每个租户只读取他自己的数据。服务器不知道这一点,并且缓存将倾向于保存所有租户的所有数据,因为(我打赌)大多数租户都会对相同的日期感兴趣。 )

尽可能使用最窄的列。不要BIGINT现在使用,以防您以后想要联合;当那一天到来时,如果它来了,ALTER TABLE一定会等着你。smalldatetime除非您需要几秒钟,否则请使用。放弃ReadId是因为您已经拥有一个自然键,它既浪费空间又是资源争用的来源。换成UIDRead一个普通的整数,希望有一天你有超过 20 亿的读者。

如果生成的表在接受插入时仍然很慢,这不是表的错。见服务器。

于 2013-03-14T02:03:01.637 回答