公司在做产品平台,数据访问使用的hibernate框架,现在开发也基本成型。但在做性能测试的时候发现一个问题,大数据量下列表分页效率非常低。
比如有个合同单据主表A(ID int,Code varchar(20),CreateTime datetime,USERID int ……) 还有其他字段就不说了,该表每天有增删,还有一张用户表B(UserID int,Name varchar(20) ……),该表增删不多。其中A表数据量100万,ID列自增主键有聚集索引,Code、Createtime和Userid有非聚集索引;B表数据量3万,UserID列主键聚集索引。
第一页的SQL语句大概这样
select top 25 a.code,b.Name from A left join B on A.UserID=b.UserID where a.code like 'TCMM%' order by a.createtime desc
如果where条件命中记录数2千左右:单独执行SQL语句时间8ms,10个并发40ms左右,数据库CPU20%。
如果where条件命中记录数2万左右:单独执行SQL语句时间60ms,10个并发150ms左右,数据库CPU90%。
当10个并发时数据库已经没有资源干其他的了,看了一下执行计划createtime排序使用了索引扫描,也就是说随着命中数增加性能直线下降。如果只是真对当前语句优化我试过两个方法,1.A.code中添加包含索引,把createtime添加进去;2.Order by排序改成code。这两个办法性能都非常好,10个并发大概1ms,数据库服务器CPU15%,每秒事务数1万多。
其实影响性能的地方很明显createtime做索引扫描,如果只是当前语句优化好办多了,但事实要针对ORM出优化解决方案。
实际情况是这样,
1、排序字段是不固定的,任何一个字段都可能排序。
2、返回字段和where条件也不确定,不一定code做筛选,包含索引用不上
3、左链接表可能有好几个,并且在where中也可能有条件限制
4、当where命中率超过2%时,10个并发用户可以把数据库服务器压死,响应时间4秒左右,每秒事务数只有5个,不能忍受啊(WEB服务器和数据库服务器性能都非常好12颗CPU,32G内存)
对于这种情况大家有什么好的解决方案吗? 小弟感激不尽~!!!
方案不好讨论,大家帮忙优化一个SQL语句吧,就是分页生成的两个语句。检索结果命中数2万条。
1、
SELECT TOP 25 (c.F_ID) AS ID_
, (c.F_CODE) AS Code_
, (c.F_CREATE_TIME) AS CreateTime_
, (c.F_NAME) AS Name_
, Dept.F_NAME AS DeptName
FROM
T_TC_CONTRACT c
LEFT OUTER JOIN T_ORG_DEPT Dept
ON c.F_DEPT_ID = Dept.F_DEPT_ID
WHERE
(1 = 1)
AND (c.F_CODE LIKE 'TCMM\_BG\_41%' ESCAPE '\'
AND (Dept.F_DEPT_ID = 1012
OR Dept.F_DEPT_ID = 1011
OR Dept.F_FULL_DEPT_ID LIKE ('1/1011/%'))
)
ORDER BY
c.F_CREATE_TIME DESC
, c.F_ID ASC
2、
SELECT count(*)
FROM
T_TC_CONTRACT c
LEFT OUTER JOIN T_ORG_DEPT Dept
ON c.F_DEPT_ID = Dept.F_DEPT_ID
WHERE
(1 = 1)
AND (c.F_CODE LIKE 'TCMM\_BG\_41%' ESCAPE '\'
AND (Dept.F_DEPT_ID = 1012
OR Dept.F_DEPT_ID = 1011
OR Dept.F_FULL_DEPT_ID LIKE ('1/1011/%')))
其中表 T_TC_CONTRACT中F_ID是自增主键和聚集索引,F_CODE和F_CREATE_TIME上有非聚集索引,其他列没有索引,数据量100万;表 T_ORG_DEPT中F_DEPT_ID上有主键和聚集索引,数据量3万。
没有并发时语句1执行时间400毫秒,语句2执行时间300毫秒左右。如果10个并发,两个语句执行时间在3秒以上。
请大家帮忙把10个并发执行时间降到1秒内,可以修改索引结构,感觉主要是count性能比较低,谢谢
搜索的时候建议使用lucene来做,这样就不怕数据多了
lucene还没有用过,研究一下看看怎么样
这么数据 like 会死人的
如果命中数据量在0.5%左右就没有问题,但实际使用肯定不会这么少,10%左右应该比较正常
试试 dapper.net