creat table TEST(ID1 number PRIMARY KEY,word VARCHAR(50),numero number);creat table TEST_CHILD (ID2 number references test(ID),word2 VARCHAR(50));CREATE INDEX TEST_IDX ON TEST_CHILD(word2);CREATE INDEX TEST_JOIN_IDX ON TEST_CHILD(ID);insert into TEST SELECT ROWNUM,U1.USERname||U2.table_name,LENGTH(U1.USERname) FROM ALL_USERS U1,ALL_tableS U2;INSERT INTO TEST_CHILD SELECT MOD(ROWNUM,15000)+1,U1.USER_ID||U2.table_name FROM ALL_USERS U1,ALL_tableS U2;
我们想查询从TEST表中获取满足子表中某些条件的行,所以我们选择:
SELECT /*+FirsT_ROWS(10)*/* FROM TEST T WHERE EXISTS (SELECT NulL FROM TEST_CHILD TC WHERE word2 like 'string%' AND TC.ID = T.ID ) AND ROWNUM < 10;
我们总是只想要前10个结果,而不再是结果.因此,我们希望获得相同的响应时间来读取10个结果,无论表有10个匹配值还是1,000,000;因为它可以从子表中获得10个不同的结果并获取父表上的值(或者至少是我们想要的计划).但在检查实际执行计划时,我们看到:
-----------------------------------------------------------------------------------------------| ID | Operation | name | Rows | Bytes | Cost (%cpu)| Time |-----------------------------------------------------------------------------------------------| 0 | SELECT STATEMENT | | 1 | 54 | 5 (20)| 00:00:01 ||* 1 | COUNT StopKEY | | | | | || 2 | nesTED LOOPS | | | | | || 3 | nesTED LOOPS | | 1 | 54 | 5 (20)| 00:00:01 || 4 | SORT UNIQUE | | 1 | 23 | 3 (0)| 00:00:01 || 5 | table ACCESS BY INDEX ROWID| TEST_CHILD | 1 | 23 | 3 (0)| 00:00:01 ||* 6 | INDEX RANGE SCAN | TEST_IDX | 1 | | 2 (0)| 00:00:01 ||* 7 | INDEX UNIQUE SCAN | SYS_C005145 | 1 | | 0 (0)| 00:00:01 || 8 | table ACCESS BY INDEX ROWID | TEST | 1 | 31 | 1 (0)| 00:00:01 |-----------------------------------------------------------------------------------------------Predicate information (IDentifIEd by operation ID):--------------------------------------------------- 1 - filter(ROWNUM<10) 6 - access("WORD2" liKE 'string%') filter("WORD2" liKE 'string%') 7 - access("TC"."ID"="T"."ID")
在StopKEY下排序UNIQUE,afaik意味着它正在读取子表中的所有结果,使得distinct最终只选择前10个,使得查询不像我们希望的那样可扩展.
我的例子中有任何错误吗?
是否有可能改进这个执行计划,以便更好地扩展?
解决方法 SORT UNIQUE将查找和排序TEST_CHILD中匹配’string%’的所有记录 – 它不会从子表中读取所有结果.你的逻辑需要这个.如果您只从TEST_CHILD中选择了与’string%’匹配的前10行,并且这10行都具有相同的ID,那么来自TEST的最终结果将只有1行.无论如何,只要’string%’匹配TEST_CHILD中相对较少的行数,您的表现就应该没问题.如果您的情况是’string%’经常匹配TEST_CHILD上的巨大记录数,那么在给定当前表的情况下,您可以做的事情并不多,以使sql更高效.在这种情况下,如果这是一个任务关键型sql,其性能与您的年度奖金相关,那么您可以使用MATERIAliZED VIEW来做一些花哨的步法,例如:在TEST_CHILD中为高基数WORD2值预先计算10个TEST行.
最后一个想法 – 一个“冒险”的解决方案,但如果你没有数千个与同一个TEST行匹配的TEST_CHILD行,它应该可以工作,如下所示:
SELECT * FROM TEST WHERE ID1 IN (SELECT ID2 FROM TEST_CHILD WHERE word2 like 'string%' AND ROWNUM < 1000) AND ROWNUM <10;
当然,您可以向上或向下调整1000,但如果它太低,您可能会发现少于10个不同的ID值,这将为您提供少于10行的最终结果.
总结以上是内存溢出为你收集整理的oracle – 改进SQL存在可伸缩性全部内容,希望文章能够帮你解决oracle – 改进SQL存在可伸缩性所遇到的程序开发问题。
如果觉得内存溢出网站内容还不错,欢迎将内存溢出网站推荐给程序员好友。
欢迎分享,转载请注明来源:内存溢出
评论列表(0条)