我在ms-sql-server express 2008中有一个数据库,可以使用同一台PC上的linq-to-sql访问。 (没有多少并发访问,但复杂的查询)
它有几个表,每个表都可以变得非常大,以至于查询,删除,更新和插入的性能变得太慢。
有一个主表项目,几乎所有其他表都有
选择,删除,更新和插入始终在单个项目上运行。 我永远不需要更新不同项目的条目或从2个项目中选择匹配的项目等。
有什么方法可以用这个事实来提高数据库的性能吗?
我已经在适用的外键project_ID上有一个非聚集索引。
还有什么我可以做的吗? 分区可以帮助我,如果它可用于sql-express吗?
编辑:
慢查询的例子(转述,大多数是linq-to-sql查询,对于一些删除我直接执行sql):
delete from items
where items.projectID=X
AND (items.prop1=a OR items.prop2=b OR items.prop3=c)
(deletes a few 1000 items, fast when database is empty, slow when lots of other projects exist)
select top 1 itemprops
from itemprops
inner join items on items.id = itemprops.itemid
inner join project on item.projectid=project.id
inner join modes on itemprops.modeId = mode.id
where item.name = X and project.id = Y and mode.name = z
(find a certain itemprop corresponding to an item and a mode)
select top 1 * from foo where projectID=x and name=Y and type=z
(nonclustered index on projectID + name + type exists)
我所有查询之间的共同点是:他们在某处都有where projectID=XY
答案 0 :(得分:0)
对于第一个语句(删除),您可以创建一个包含两个连接字段的新的非聚集索引:
CREATE NONCLUSTERED INDEX <MeaningfulIndexName>
ON Items (ProjectID)
INCLUDE (Prop1, Prop2, Prop3)
最后一个SELECT查询也是如此。优化器应该意识到这个索引将产生更好的计划并使用它 - 检查查询计划,如果没有,请查看索引提示。您也可以删除OR,只需执行三个单独的删除查询。
在最后两个中,确保使用ORDER BY子句,以便查询知道您想要的TOP。中间的一个很难:没有索引所有内容(再次检查查询计划),您可能想看看是否可以避免加入该“名称”字段并尝试使用ID。我知道并不总是可行,但SQL在比较数字而不是字符串方面更胜一筹。
答案 1 :(得分:0)
我在数据库中使用索引或各种设置的所有尝试都没有显着提高性能。
这最终对我有用:
用于此类查询:
delete from items
where items.projectID=X
AND (items.prop1=a OR items.prop2=b OR items.prop3=c)
我没有批量删除符合条件的所有项目,而是使用ON DELETE CASCADE
update items set items.projectID=DummyProjectID
where items.projectID=X
AND (items.prop1=a OR items.prop2=b OR items.prop3=c)
出于某种原因,这比简单地删除项目要快得多。创建新项目并更新几千个项目几乎立即发生,删除项目至少比直接删除项目快10倍。
对于这些类型的查询:
select top 1 itemprops ...
将项目的所有itemprops加载到字典中一次,然后回答来自此本地缓存的所有查询要快得多。它不是很优雅,我必须记住每次更改后更新缓存,但它可以工作。