好久没发帖提问了。问个ORACLE的性能问题(菜鸟级。。)

2012-11-28 17:44:01 +08:00
 kojp
两个表大概60w行的数据吧。
其中一个做了索引,一个没做。
一个简单的关联查询。
耗时不有点不正常(相比以前)


查询语句是这样的。
table1 中有c1,c2 等字段
table2中有id,name等字段

select c1 from table1 t1,table2 t2 where t2.id='20121128' and t1.c2=t2.name

现在的耗时是0.9s 到 10s 不等。
(超过2s就影响到前台的性能了,现在超过2s的比率大概在30%以上了!)

服务器配置是 4G 内存,双核,(虽然是很次的服务器,但物理性能上,没看出IO,CPU,内存之类的不够用)。

系统,是大家都乐意吐糟的SERVER2003

求解两个问题:
1,查询时间为什么是随机的,而且相差比较大?对于60W行的数据,正常的速度应该是什么样的?
2,语句上面,是否有优化的可能性?
3,给两个表都做索引和只给其中一个表做索引性能上会有区别吗?(其中T2已经有索引)


谢谢~~~(PS:Oracle太笨重了,以前很少接触。只能是现学现卖)





















(记得以前不是/new/qna呀!)
3548 次点击
所在节点    Oracle
12 条回复
Muninn
2012-11-28 18:22:34 +08:00
这里估计没几个人搞商业数据库。我算是略懂。
第一你没说索引加哪里了,建议涉及的三个字段分别加单字段索引。第二你需要定期run statistics 。第三建议早点把操作系统换了。你的机配置也就是个oracle的最低配置。。。。
manoon
2012-11-28 19:06:49 +08:00
@Muninn

谢谢

索引只做了t2的id
statics 是什么我地会儿回去查一下.
话说: 在存储和和系平台不更改, 数据库也不做任何优化的情况下.如果直接上一台32g内存, 6核cpu的话. 能解决问题么?
Muninn
2012-11-28 21:16:42 +08:00
查询时间不稳定肯定不是增加配置能搞定的
要是多数时间较长偶尔很快,那是命中缓存了,数据库每次会读整页的数据到内存,并不是整行,所以有可能你要查的刚好在内存。
要是大部分时间较短偶尔较长,就要查那一瞬间是什么东西把数据库资源抢夺了或者阻塞了。
其实找个你同事看看执行计划基本就知道怎么了。
kojp
2012-11-28 23:34:29 +08:00
@Muninn

大谢!

关键词------执行计划!

(同事在外地,机关内网,木有办法远程)

再提供一些信息。
1,关于命中缓存。用相关的脚本测试了一下 ,结果是96%以上。
2,当执行insert 语句的时候,很快!(这可能是废话,因为写入不需要从60W的“茫茫人海”中读东西)
3, “并发”查询越多的时候,越慢,几乎有80%以上的查询是在10s左右,甚至更长。
4,我去补课一下“执行计划”(我会告诉你我现在连SYSDBA权限都没有么 :-(。。。)


PS:
我有一个弱弱的想法。不知道能成立否。
这个想法是通过查询run statistics 这个关键词得来的。
可不可以,做一张类似于虚拟表的东西出来。就是说,我不从60W数据中查询。
我从最近的1W条数据中查询。

select c1 from ( select * from table1 where rownum<10000 ) t1,( select * from table1 where rownum<10000 ) t2 where t2.id='20121128' and t1.c2=t2.name 类似于,这个意思。我不知道,我表达清楚了没有。


再次,深深地鞠躬感谢一下!!!
即使问题没能解决。也学到了不少知识~~~
moriz
2012-11-28 23:41:18 +08:00
应该就是索引的事, 耗时不同,是因为 t2.id='20121128' 这个条件匹配的记录数不一样
moriz
2012-11-28 23:43:14 +08:00
匹配到记录数多,没加索引的那张表的全表扫描次数就多
Muninn
2012-11-28 23:54:52 +08:00
有的时候你不太了解oracle的解释机制,也有的时候它有些笨。
在表大量更新后需要做run statistics ,所以频繁更新的表需要用定时任务跑run statistics。
而执行计划里它如果还没有先取出t2的id的那条记录然后关联的话,你又着急,可以手动解决。
先写个子查询把t2必要的字段取出来,用id的条件限定。因为id是索引,这是瞬间就出来的。然后再用这个子查询关联t1表,只要关联的条件两边都是索引,也会及其的快。

关于你说的虚拟表,有现成的方法。 就是oracle的分区表。 你开始没说过你可以限制从某一部分数据查,如果你能有准确找到让数据分布的条件,比如时间,日期,或者id之类的,你可以做分区表。oracle会先用分区条件把搜索范围限制在一个分区中。
不过几十万大材小用了。应该用不到。
我们都是记录上亿了才开始用分区表。几千万都不怕的。。。
所以你几十万要是有问题,而如果表又不是特别宽的话,那很可能是什么很低级的地方出问题了。

不知道你的表有多宽,所有字段的长度加起来要尽量的压缩,使用varchar2不要用char 如果一行太宽,全部从硬盘中读到内存中的io开销很大。
kojp
2012-11-29 00:18:15 +08:00
@Muninn
@moriz

谢谢,有你们这两条回复。我心里就有几分把握了。哈哈~~~

先把索引搞起!
然后写个crontab
再找其它的,小BUG。

ps:关于你说的字查询,是不是要更改查询语句了?
改成

select c1 from table1 t1 where t1.c2=(select t2.name from table2 t2 where t2.id='20121128' ))

这样咩(感觉有点不通顺。。。)
Muninn
2012-11-29 00:26:53 +08:00
select t1.c1 from table1 t1,(select t2.name as name from table2 t2 where t2.id='20121128' ) t3 where t1.c2=t3.name 这是oracle语法
select t1.c1 from table t1
join (select t2.name as name from table2 t2 where t2.id='20121128' ) t3
on t1.c2=t3.name 这是标准SQL
select t1.c1 from table1 t1 where t1.c2 in (select t2.name as name from table2 t2 where t2.id='20121128' ) in不会走索引 但是括号里的结果集要是很小也不慢
coldear
2012-11-29 00:34:35 +08:00
先看execution plan。。
如果你的c2和name没有加index,这个查询效率肯定高不了,
select c1有可能做一次lkey ookup,这个也很影响效率
coldear
2012-11-29 00:35:21 +08:00
*key lookup
manoon
2012-11-29 15:32:36 +08:00
结帖! ! ! 谢谢各位!
已经搞定. . . 就是索引的问题
现在的查询测试都在1s 以内.
.( 我会告诉你们原来这两个表连主键都没有么)

这是一个专为移动设备优化的页面(即为了让你能够在 Google 搜索结果里秒开这个页面),如果你希望参与 V2EX 社区的讨论,你可以继续到 V2EX 上打开本讨论主题的完整版本。

https://www.v2ex.com/t/53540

V2EX 是创意工作者们的社区,是一个分享自己正在做的有趣事物、交流想法,可以遇见新朋友甚至新机会的地方。

V2EX is a community of developers, designers and creative people.

© 2021 V2EX