我们正在生产系统上遇到性能问题,其中唯一的索引是主键上的聚簇索引.
所有的sql select语句都是以他们的linq中的tenantid开头的实体语句
invoiceitems.tenantid = thecurrenttenantid order by invoicedate
当前图
租户(tenantid uniqueidentifier主键,租户名)
外键(tenantid)
索引(集合在tenantid上)
客户(tenantid uniqueidentifier,customerid uniqueidentifier主键,customername varchar(50))
外键(tenantid,customerid)
索引(聚集在customerid上)
发票(tenantid uniqueidentifier,invoiceid uniqueidentifier主键,billcustomerid uniqueidentifier,shipcustomerid uniqueidentifier,invoicedate datetime)
外键(tenantid,billcustomerid,shipcustomerid)
索引(集群在发票上)
InvoiceItems(tenantid uniqueidentifier,invoiceitemid uniqueidentifier primarykey,invoiceid uniqueidentifier,lineitemorder int)
外键(tenantid,invoiceid)
索引(聚集在invoiceitemid上)
sqlAzure要求每个表都有一个聚簇索引,所以它目前只是在primarykeyid,因为这是默认的.现在这是每个表上唯一的索引.在整个系统的表中有各种外键,并且没有一个外键表字段被索引.
我们现在正在尝试解决一些性能问题,并且想知道什么是最好的聚集索引,以及任何其他索引可能是有帮助的.我们希望我们不必改变现有的聚集索引,除非我们绝对必须,但我们愿意这样做.在sqlAzure AFAIK中,您不能简单地调整现有表中的聚簇索引 – 您必须使用所需的聚簇索引创建一个新表,并将所有记录从旧表插入新表(并处理所有外键约束等)表依赖性).
所有的sql select语句都以tenantid开头,在他们的linq到entity语句中.
invoiceitems.tenantid = thecurrenttenantid order by invoicedate
一些sql select语句只是有一个顺序 – 有些在引入子表时有其他连接条件值
invoiceitems.tenantid = thecurrenttenantid and invoice.invoiceid = invoiceitems.invoiceid order by invoicedate
这里有几个想法(除了这个外,我们对其他人开放) – 哪些是最好的,为什么?
主要指标选项
加快租户记录的访问
选项1 – 在tenantid上添加非聚集索引
发票(tenantid uniqueidentifier,shipcustomerid)
索引(集群在发票上,非群集在tenantid上)
选项2 – 将主键从primaryid更改为tenantid primaryid,并将集群索引更改为tenantid primaryid.
发票(tenantid uniqueidentifier主键,shipcustomerid)
索引(聚集在tenantid invoiceid上)
外国主要索引选项
加快连接
选项3 – 仅在foreignkeyid上的所有外键字段上添加非聚集索引.
发票(tenantid uniqueidentifier,shipcustomerid)
索引(集群在invoiceid上,非集群在billcustomerid上,非集群在shipcustomerid上)
选项4 – 将所有外键从foreignkeyid更改为tenantid foreignkeyid,并在tenantid foreignkeyid上添加索引
发票(tenantid uniqueidentifier,tenantid billcustomerid,tenantid shipcustomerid)
索引(集群在发票上,非群集在tenantid billcustomerid上,非群集在tenantid shipcustomerid上)
sql SELECT优化索引选项
加快经常使用的查询,如从发票的选择字段,其中tenantid = value order by invoicedate
选项5 – 除了tenantid之外,在每个表格中最常使用的排序顺序字段中添加索引.
发票(tenantid uniqueidentifier,非集群在发票上)
选项6 – 在每个表格中的tenantid“最常用的排序顺序字段”中添加索引,并在tenantid“最常用的排序顺序字段”上添加非聚集索引
发票(tenantid uniqueidentifier,非聚簇在开发票单上)
解决方法
对于你的情况,有几个提示让你开始.当您使用LINQ时,您无法直接访问在sql中运行的实际查询.您可能会认为您应该看到什么样的查询,但根据您使用的是哪个版本的EF,可以对如何构建查询做出一些有意思的决定.要准确找出正在运行的查询,您需要使用sql Profiler.不幸的是,sql Profiler不适用于sql Azure,因此您将希望在某个本地服务器上获取您的数据库副本,并运行您的应用程序指向本地. sql Server Management Studio(SSMS)中的export data tier application和相关import对此非常有用.
通过实际查询,您可以使用Azure中的数据库在SSMS中运行它们以获取执行计划.然后,您可以更改索引,再次运行查询并比较计划.如果你不想混淆你的主开发数据库,你可以很容易地用CREATE DATABASE xxx AS COPY OF yyyy创建一个副本.
不要试图在本地DB上进行优化. sql Azure具有与大多数内部sql安装不同的性能轮廓.
所有这一切都表示,如果您所有的查询总是包含租户ID,那么是的,我希望将其包含为群集索引的第一部分可以提高查询性能.对于所有其他索引,我不太确定,所以我会衡量,衡量,测量.还要记住,索引不是免费的,每一个你创建的影响你的写性能和数据库的大小,所以我不会坚持和索引的一切.
最后,不用担心为你的PK使用guids,如果你的DB足够大,你需要通过租户ID(你的结构看起来像处理相当不错)IDENTITY列停止成为一个选项.