比如我现在是 200,0000 条记录,
页面 是: 首页 上一页 下一页 尾页
点首页或点下一页查询很快,但点尾页就要十几秒才能查询到,此时再点上一页也是需要十几秒才能查询到
也就是说越往后的数据查询的越慢,有什么好的办法能解决此问题?
有没有比较好的方法能显著提升速度?
31 个解决方案
#1
优化数据库,在相关字段上建索引。或者采用分区表之类的。
hib一般也用的是数据库的分页,比如oracle的rownum等,单纯从sql上来说,很难优化了。
200w的数据量,通常查最后几页都需要差不多这个时间(存在order by)。
hib一般也用的是数据库的分页,比如oracle的rownum等,单纯从sql上来说,很难优化了。
200w的数据量,通常查最后几页都需要差不多这个时间(存在order by)。
#2
优化数据库
感觉用hibernate做分页 很多小细节要注意的
#3
优化数据库,在相关字段上建索引。或者采用分区表之类的。
优化数据库,在相关字段上建索引
我没用过,不知道怎么操作,能否详细说一下?与存储过程相比呢?
我用的是SqlServer2005
优化数据库,在相关字段上建索引
我没用过,不知道怎么操作,能否详细说一下?与存储过程相比呢?
我用的是SqlServer2005
#4
sqlserver不懂。
把hib生成的sql晒下?看看你有没有索引。。
#5
对了存储过程肯定也跟hib一样是用数据库的分页来做的了。如果sql一样的话,存储过程和hib调用,性能区别不会很大。
#6
Hibernate: select top 10 guestbook0_.id as id0_, guestbook0_.name as name0_, gue
stbook0_.email as email0_, guestbook0_.url as url0_, guestbook0_.title as title0
_, guestbook0_.context as context0_, guestbook0_.time as time0_ from guestBook.d
bo.guestBook guestbook0_ order by guestbook0_.id asc
#7
create index my_index on guestBook(id)
建立索引了速度好象还是一样慢!
是不是在数据库创建了索引就可以了?是否要象存储过程那样引用呢?
建立索引了速度好象还是一样慢!
是不是在数据库创建了索引就可以了?是否要象存储过程那样引用呢?
#8
关注中
#9
mark
#10
order by guestbook0_.id
ID是主键的话,已经有索引了,你这里又没有where条件可作优化。。。
ID不是主键的话,看看ID上面有没有索引,没有的话,建一个。
create index idx_gbook_id on 表名(列名); --表名指数据库表名,列名指ID。这句话在数据库中做。
你这里没有where条件,一次全取200w排序。。。,从数据库来看,也没有办法分区优化了。。。。
楼主认命吧,或者加内存,加cpu。。。
ID是主键的话,已经有索引了,你这里又没有where条件可作优化。。。
ID不是主键的话,看看ID上面有没有索引,没有的话,建一个。
create index idx_gbook_id on 表名(列名); --表名指数据库表名,列名指ID。这句话在数据库中做。
你这里没有where条件,一次全取200w排序。。。,从数据库来看,也没有办法分区优化了。。。。
楼主认命吧,或者加内存,加cpu。。。
#11
id为主键,等于有索引了
速度还是很慢,Hinernate 难道只能就这样了?
速度还是很慢,Hinernate 难道只能就这样了?
#12
没办法,我的机器1G内存,双核,也是只有PK的索引,oracle92数据库,200w数据,有order by,取最后10条也差不多这个时间(sql跟你的一样。。。)
#13
使用hibernate建议配上二级缓存,不然数据量大了,是非常耗性能的,而且你的延迟加载等等都得设置好,和主控,级联,不然极有可能把你的整个数据库给load出来
hibernate做的最好的就是缓存
hibernate做的最好的就是缓存
#14
哦?二级缓存什么意思?是不是比如我每页要查10条,但是它给我查一百条出来,然后每次翻页就从缓存里面拿啊?如果不是这样的话,难道200w也一次都放内存?
我不懂hib啊,纯粹瞎猜的,不用当真。
#15
可以从多方面下手:第一,可以为查询的设置索引;第二,优化查询,使用数据库分页(如Oracle的伪列);第三,用数据库存储过程来分页,返回一页的数据,也挺好。
#16
二级缓存 什么个意思?
怎么设置?
#17
也在研究这问题.关注此贴
#18
学习
#19
你项目真大。百w级数据。
#20
mark,关注 。。。
#21
jdbc 试试
#22
学习中..
#23
曾经看过一个人问SQL SERVER 2000如何去除伪分页 我才知道 HIBERNATE在SQL SERVER 2000里用的是伪分页 后来SQLSERVER 2005有类似Oracle的分页函数了之后 就可以通过修改数据库方言 让HIBERNATE支持真分页了
http://blog.csdn.net/tdl982324/archive/2008/07/03/2607674.aspx
LZ看这个
http://blog.csdn.net/tdl982324/archive/2008/07/03/2607674.aspx
LZ看这个
#24
这么写,where条件也没有,建了索引也用不到,每次运行都是从表的起始位置开始一行行扫描,当然越往后越慢了。
#25
//查找记录
public List getAllGuestBooks(int firstResult,int maxResult){
Session session = this.getSession();
System.out.println("all");
List list = null;;
try {
Query query = session.createQuery("from GuestBook order by id asc");
query.setFirstResult(firstResult).setMaxResults(maxResult);
list = query.list();
} catch (HibernateException e) {
e.printStackTrace();
} finally{
session.close();
}
return list;
}
id为主键,我是传的是参数啊query.setFirstResult(firstResult).setMaxResults(maxResult);
#26
想用到id这个索引,sql语句要类似这样: select * from GuestBook where id = ?
select * from GuestBook这样是用不到的。
另外"from GuestBook order by id asc"这句得优化,把order by id asc去掉,id是主键,本身就是排好序的了
select * from GuestBook这样是用不到的。
另外"from GuestBook order by id asc"这句得优化,把order by id asc去掉,id是主键,本身就是排好序的了
#27
sql语句我知道,如果是通过别的字段排序,怎么提高效率呢?比如通过name查询,by name desc
query.setFirstResult(firstResult).setMaxResults(maxResult);
这是设置从哪条数据查,一次查询多少条数据
#28
跟一次查多少条关系不大,界面上强制加查询条件吧,然后用到索引。比如name字段建立索引,查询的时候类似这样:from GuestBook where name like 'AAA%'
order by尽量不要加了。
其实想想,对一个几百万的大表做分页显示,还不加任何查询条件,好象没什么必要。
order by尽量不要加了。
其实想想,对一个几百万的大表做分页显示,还不加任何查询条件,好象没什么必要。
#29
没有正式用过Hibernate..
但看过Hibernate的源码,,Hibernate 2针对于sqlserver 的分页只是逻辑分页。。
好像Hibernate 3也是逻辑分页。。。
只会在sql数据的时候在上top,只有第一页数据会出现的比较快,,而后翻页是查询出来的数据越来越多,再通过翻动游标返回数据。。。
像我正在用的ibatis也是如此,,,这些orm都唯独不支持sqlserver的物理分页。。
解决办法,,,楼主网上应该一大吧。。。基本上应该重载sqlserver的方言。。。
其实200w的数据也不算多,,,
贴点源码:
orcle:
public String getLimitString(String sql, boolean hasOffset) {
sql = sql.trim();
boolean isForUpdate = false;
if ( sql.toLowerCase().endsWith(" for update") ) {
sql = sql.substring( 0, sql.length()-11 );
isForUpdate = true;
}
StringBuffer pagingSelect = new StringBuffer( sql.length()+100 );
if (hasOffset) {
pagingSelect.append("select * from ( select row_.*, rownum rownum_ from ( ");
}
else {
pagingSelect.append("select * from ( ");
}
pagingSelect.append(sql);
if (hasOffset) {
pagingSelect.append(" ) row_ where rownum <= ?) where rownum_ > ?");
}
else {
pagingSelect.append(" ) where rownum <= ?");
}
if ( isForUpdate ) {
pagingSelect.append( " for update" );
}
return pagingSelect.toString();
}
sqlserver:
public String getLimitString(String querySelect, int offset, int limit) {
if ( offset > 0 ) {
throw new UnsupportedOperationException( "sql server has no offset" );
}
return new StringBuffer( querySelect.length()+8 )
.append(querySelect)
.insert( getAfterSelectInsertPoint(querySelect), " top " + limit )
.toString();
}
但看过Hibernate的源码,,Hibernate 2针对于sqlserver 的分页只是逻辑分页。。
好像Hibernate 3也是逻辑分页。。。
只会在sql数据的时候在上top,只有第一页数据会出现的比较快,,而后翻页是查询出来的数据越来越多,再通过翻动游标返回数据。。。
像我正在用的ibatis也是如此,,,这些orm都唯独不支持sqlserver的物理分页。。
解决办法,,,楼主网上应该一大吧。。。基本上应该重载sqlserver的方言。。。
其实200w的数据也不算多,,,
贴点源码:
orcle:
public String getLimitString(String sql, boolean hasOffset) {
sql = sql.trim();
boolean isForUpdate = false;
if ( sql.toLowerCase().endsWith(" for update") ) {
sql = sql.substring( 0, sql.length()-11 );
isForUpdate = true;
}
StringBuffer pagingSelect = new StringBuffer( sql.length()+100 );
if (hasOffset) {
pagingSelect.append("select * from ( select row_.*, rownum rownum_ from ( ");
}
else {
pagingSelect.append("select * from ( ");
}
pagingSelect.append(sql);
if (hasOffset) {
pagingSelect.append(" ) row_ where rownum <= ?) where rownum_ > ?");
}
else {
pagingSelect.append(" ) where rownum <= ?");
}
if ( isForUpdate ) {
pagingSelect.append( " for update" );
}
return pagingSelect.toString();
}
sqlserver:
public String getLimitString(String querySelect, int offset, int limit) {
if ( offset > 0 ) {
throw new UnsupportedOperationException( "sql server has no offset" );
}
return new StringBuffer( querySelect.length()+8 )
.append(querySelect)
.insert( getAfterSelectInsertPoint(querySelect), " top " + limit )
.toString();
}
#30
数据优化一直是难题, 学习....
#31
学习中...
#1
优化数据库,在相关字段上建索引。或者采用分区表之类的。
hib一般也用的是数据库的分页,比如oracle的rownum等,单纯从sql上来说,很难优化了。
200w的数据量,通常查最后几页都需要差不多这个时间(存在order by)。
hib一般也用的是数据库的分页,比如oracle的rownum等,单纯从sql上来说,很难优化了。
200w的数据量,通常查最后几页都需要差不多这个时间(存在order by)。
#2
优化数据库
感觉用hibernate做分页 很多小细节要注意的
#3
优化数据库,在相关字段上建索引。或者采用分区表之类的。
优化数据库,在相关字段上建索引
我没用过,不知道怎么操作,能否详细说一下?与存储过程相比呢?
我用的是SqlServer2005
优化数据库,在相关字段上建索引
我没用过,不知道怎么操作,能否详细说一下?与存储过程相比呢?
我用的是SqlServer2005
#4
sqlserver不懂。
把hib生成的sql晒下?看看你有没有索引。。
#5
对了存储过程肯定也跟hib一样是用数据库的分页来做的了。如果sql一样的话,存储过程和hib调用,性能区别不会很大。
#6
Hibernate: select top 10 guestbook0_.id as id0_, guestbook0_.name as name0_, gue
stbook0_.email as email0_, guestbook0_.url as url0_, guestbook0_.title as title0
_, guestbook0_.context as context0_, guestbook0_.time as time0_ from guestBook.d
bo.guestBook guestbook0_ order by guestbook0_.id asc
#7
create index my_index on guestBook(id)
建立索引了速度好象还是一样慢!
是不是在数据库创建了索引就可以了?是否要象存储过程那样引用呢?
建立索引了速度好象还是一样慢!
是不是在数据库创建了索引就可以了?是否要象存储过程那样引用呢?
#8
关注中
#9
mark
#10
order by guestbook0_.id
ID是主键的话,已经有索引了,你这里又没有where条件可作优化。。。
ID不是主键的话,看看ID上面有没有索引,没有的话,建一个。
create index idx_gbook_id on 表名(列名); --表名指数据库表名,列名指ID。这句话在数据库中做。
你这里没有where条件,一次全取200w排序。。。,从数据库来看,也没有办法分区优化了。。。。
楼主认命吧,或者加内存,加cpu。。。
ID是主键的话,已经有索引了,你这里又没有where条件可作优化。。。
ID不是主键的话,看看ID上面有没有索引,没有的话,建一个。
create index idx_gbook_id on 表名(列名); --表名指数据库表名,列名指ID。这句话在数据库中做。
你这里没有where条件,一次全取200w排序。。。,从数据库来看,也没有办法分区优化了。。。。
楼主认命吧,或者加内存,加cpu。。。
#11
id为主键,等于有索引了
速度还是很慢,Hinernate 难道只能就这样了?
速度还是很慢,Hinernate 难道只能就这样了?
#12
没办法,我的机器1G内存,双核,也是只有PK的索引,oracle92数据库,200w数据,有order by,取最后10条也差不多这个时间(sql跟你的一样。。。)
#13
使用hibernate建议配上二级缓存,不然数据量大了,是非常耗性能的,而且你的延迟加载等等都得设置好,和主控,级联,不然极有可能把你的整个数据库给load出来
hibernate做的最好的就是缓存
hibernate做的最好的就是缓存
#14
哦?二级缓存什么意思?是不是比如我每页要查10条,但是它给我查一百条出来,然后每次翻页就从缓存里面拿啊?如果不是这样的话,难道200w也一次都放内存?
我不懂hib啊,纯粹瞎猜的,不用当真。
#15
可以从多方面下手:第一,可以为查询的设置索引;第二,优化查询,使用数据库分页(如Oracle的伪列);第三,用数据库存储过程来分页,返回一页的数据,也挺好。
#16
二级缓存 什么个意思?
怎么设置?
#17
也在研究这问题.关注此贴
#18
学习
#19
你项目真大。百w级数据。
#20
mark,关注 。。。
#21
jdbc 试试
#22
学习中..
#23
曾经看过一个人问SQL SERVER 2000如何去除伪分页 我才知道 HIBERNATE在SQL SERVER 2000里用的是伪分页 后来SQLSERVER 2005有类似Oracle的分页函数了之后 就可以通过修改数据库方言 让HIBERNATE支持真分页了
http://blog.csdn.net/tdl982324/archive/2008/07/03/2607674.aspx
LZ看这个
http://blog.csdn.net/tdl982324/archive/2008/07/03/2607674.aspx
LZ看这个
#24
这么写,where条件也没有,建了索引也用不到,每次运行都是从表的起始位置开始一行行扫描,当然越往后越慢了。
#25
//查找记录
public List getAllGuestBooks(int firstResult,int maxResult){
Session session = this.getSession();
System.out.println("all");
List list = null;;
try {
Query query = session.createQuery("from GuestBook order by id asc");
query.setFirstResult(firstResult).setMaxResults(maxResult);
list = query.list();
} catch (HibernateException e) {
e.printStackTrace();
} finally{
session.close();
}
return list;
}
id为主键,我是传的是参数啊query.setFirstResult(firstResult).setMaxResults(maxResult);
#26
想用到id这个索引,sql语句要类似这样: select * from GuestBook where id = ?
select * from GuestBook这样是用不到的。
另外"from GuestBook order by id asc"这句得优化,把order by id asc去掉,id是主键,本身就是排好序的了
select * from GuestBook这样是用不到的。
另外"from GuestBook order by id asc"这句得优化,把order by id asc去掉,id是主键,本身就是排好序的了
#27
sql语句我知道,如果是通过别的字段排序,怎么提高效率呢?比如通过name查询,by name desc
query.setFirstResult(firstResult).setMaxResults(maxResult);
这是设置从哪条数据查,一次查询多少条数据
#28
跟一次查多少条关系不大,界面上强制加查询条件吧,然后用到索引。比如name字段建立索引,查询的时候类似这样:from GuestBook where name like 'AAA%'
order by尽量不要加了。
其实想想,对一个几百万的大表做分页显示,还不加任何查询条件,好象没什么必要。
order by尽量不要加了。
其实想想,对一个几百万的大表做分页显示,还不加任何查询条件,好象没什么必要。
#29
没有正式用过Hibernate..
但看过Hibernate的源码,,Hibernate 2针对于sqlserver 的分页只是逻辑分页。。
好像Hibernate 3也是逻辑分页。。。
只会在sql数据的时候在上top,只有第一页数据会出现的比较快,,而后翻页是查询出来的数据越来越多,再通过翻动游标返回数据。。。
像我正在用的ibatis也是如此,,,这些orm都唯独不支持sqlserver的物理分页。。
解决办法,,,楼主网上应该一大吧。。。基本上应该重载sqlserver的方言。。。
其实200w的数据也不算多,,,
贴点源码:
orcle:
public String getLimitString(String sql, boolean hasOffset) {
sql = sql.trim();
boolean isForUpdate = false;
if ( sql.toLowerCase().endsWith(" for update") ) {
sql = sql.substring( 0, sql.length()-11 );
isForUpdate = true;
}
StringBuffer pagingSelect = new StringBuffer( sql.length()+100 );
if (hasOffset) {
pagingSelect.append("select * from ( select row_.*, rownum rownum_ from ( ");
}
else {
pagingSelect.append("select * from ( ");
}
pagingSelect.append(sql);
if (hasOffset) {
pagingSelect.append(" ) row_ where rownum <= ?) where rownum_ > ?");
}
else {
pagingSelect.append(" ) where rownum <= ?");
}
if ( isForUpdate ) {
pagingSelect.append( " for update" );
}
return pagingSelect.toString();
}
sqlserver:
public String getLimitString(String querySelect, int offset, int limit) {
if ( offset > 0 ) {
throw new UnsupportedOperationException( "sql server has no offset" );
}
return new StringBuffer( querySelect.length()+8 )
.append(querySelect)
.insert( getAfterSelectInsertPoint(querySelect), " top " + limit )
.toString();
}
但看过Hibernate的源码,,Hibernate 2针对于sqlserver 的分页只是逻辑分页。。
好像Hibernate 3也是逻辑分页。。。
只会在sql数据的时候在上top,只有第一页数据会出现的比较快,,而后翻页是查询出来的数据越来越多,再通过翻动游标返回数据。。。
像我正在用的ibatis也是如此,,,这些orm都唯独不支持sqlserver的物理分页。。
解决办法,,,楼主网上应该一大吧。。。基本上应该重载sqlserver的方言。。。
其实200w的数据也不算多,,,
贴点源码:
orcle:
public String getLimitString(String sql, boolean hasOffset) {
sql = sql.trim();
boolean isForUpdate = false;
if ( sql.toLowerCase().endsWith(" for update") ) {
sql = sql.substring( 0, sql.length()-11 );
isForUpdate = true;
}
StringBuffer pagingSelect = new StringBuffer( sql.length()+100 );
if (hasOffset) {
pagingSelect.append("select * from ( select row_.*, rownum rownum_ from ( ");
}
else {
pagingSelect.append("select * from ( ");
}
pagingSelect.append(sql);
if (hasOffset) {
pagingSelect.append(" ) row_ where rownum <= ?) where rownum_ > ?");
}
else {
pagingSelect.append(" ) where rownum <= ?");
}
if ( isForUpdate ) {
pagingSelect.append( " for update" );
}
return pagingSelect.toString();
}
sqlserver:
public String getLimitString(String querySelect, int offset, int limit) {
if ( offset > 0 ) {
throw new UnsupportedOperationException( "sql server has no offset" );
}
return new StringBuffer( querySelect.length()+8 )
.append(querySelect)
.insert( getAfterSelectInsertPoint(querySelect), " top " + limit )
.toString();
}
#30
数据优化一直是难题, 学习....
#31
学习中...