Warning: file_get_contents(/data/phpspider/zhask/data//catemap/5/sql/81.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
Sql 连接具有数百万行的表_Sql_Database_Performance_Oracle_Oracle10g - Fatal编程技术网

Sql 连接具有数百万行的表

Sql 连接具有数百万行的表,sql,database,performance,oracle,oracle10g,Sql,Database,Performance,Oracle,Oracle10g,下面的sql返回35k行,运行大约需要10分钟。两个表都有数百万行。如何改进此sql SELECT /*+ index(T_DIRECTORY X_DIR) */ DIRx.dir_id , base.id FROM T_DIRECTORY DIRx, T_PERSON base WHERE

下面的sql返回35k行,运行大约需要10分钟。两个表都有数百万行。如何改进此sql

SELECT /*+ index(T_DIRECTORY X_DIR) */ 
                 DIRx.dir_id ,                   
                 base.id       
                 FROM T_DIRECTORY DIRx,  T_PERSON base 
                 WHERE 
                   DIRx.id = 26463
                   and DIRx.PERSONID=  base.PERSONID

'| Id  | Operation                    | Name           |'
'-------------------------------------------------------'
'|   0 | SELECT STATEMENT             |                |'
'|   1 |  NESTED LOOPS                |                |'
'|   2 |   TABLE ACCESS BY INDEX ROWID| T_DIRECTORY |'
'|   3 |    INDEX RANGE SCAN          | X_DIRECTORY |'
'|   4 |   TABLE ACCESS BY INDEX ROWID| T_PERSON      |'
'|   5 |    INDEX UNIQUE SCAN         | I_PERSON      |'

首先,确保在where子句(DIRx.id)中的列和正在联接的表(base.personid)上有合适的索引,并确保对这些索引进行分析,以便它们表示表中的数据-如果不进行分析,Oracle可能会在使用索引时执行完整的表扫描

SELECT INDEX_NAME, 
       NUM_ROWS, 
       LAST_ANALYZED 
  FROM DBA_INDEXES 
 WHERE TABLE_NAME IN ('T_DIRECTORY','T_PERSON');
此外,您还通过使用提示强制它使用索引,但是如果一个表比另一个表小,则哈希连接可能是更好的解决方案,因此可以尝试完全删除提示,看看是否有帮助

并行查询

当这个SQL运行时,您是否有多个CPU而没有其他任何东西在运行?例如,它是批处理过程的一部分,还是可以同时调用多次的在线过程的一部分。如果批处理过程中有多个CPU,请尝试并行查询,但如果是联机程序,则不要这样做(例如,使用并行查询的报告将尝试使用所有可用的CPU,如果同时运行多次或每个CPU核运行的并行线程数超过2个,则性能可能会变得更差)

实际上,每4个线程的并行线程执行时间大约为执行时间的一半

聚集表/索引

如果这些表总是以这种方式连接,则可以考虑一个聚集表(Oracle将在同一个块中存储每个表的连接行),这样就不必花太长时间来检索所连接的部分,但是如果您也频繁地访问其中一个表,则这可能会有缺点。 上下文


孤立地查看一个查询并不总是能找到最佳答案-在可能出错的情况下快速执行某项操作也无济于事,因此请查看上下文,即,一旦返回35000行,您将如何处理这些行,它们是否仅是今天添加的行,是否有一个表具有可以替代使用的子集?

首先,请确保您在where子句(DIRx.id)中的列和正在联接的表(base.personid)上保存适当的索引,并对这些索引进行分析,以便它们表示表中的数据-如果不进行分析,Oracle可能会在使用索引时执行完整的表扫描

SELECT INDEX_NAME, 
       NUM_ROWS, 
       LAST_ANALYZED 
  FROM DBA_INDEXES 
 WHERE TABLE_NAME IN ('T_DIRECTORY','T_PERSON');
此外,您还通过使用提示强制它使用索引,但是如果一个表比另一个表小,则哈希连接可能是更好的解决方案,因此可以尝试完全删除提示,看看是否有帮助

并行查询

当此SQL运行时,您是否有多个CPU而没有其他任何东西在运行?例如,它是批处理过程的一部分还是可以同时调用多次的联机过程的一部分。如果批处理过程和您有多个CPU,请尝试并行查询,但如果是联机程序,请不要执行此操作(例如,使用并行查询的报告将尝试使用所有可用的CPU,如果同时运行多次或每个CPU核运行的并行线程数超过2个,则性能可能会变得更差

实际上,每4个线程的并行线程执行时间大约为执行时间的一半

聚集表/索引

如果这些表总是以这种方式连接,则可以考虑一个聚集表(Oracle将在同一个块中存储每个表的连接行),这样就不必花太长时间来检索所连接的部分,但是如果您也频繁地访问其中一个表,则这可能会有缺点。 上下文


孤立地看一个查询并不总是能找到最好的答案——在可能是错误的情况下快速地做一些事情也无济于事,因此请看一下上下文,即一旦返回35000行,您将如何处理这些行,它们是否只是今天添加的行,是否有一个表具有可以替代使用的子集?

我不得不反规范化e表格。

我不得不对表格进行非规范化

“我不得不对表格进行非规范化”

在OLTP中,数据库去规范化总是一个坏消息。它会加快一些查询,但也会减慢其他查询的速度。最好的情况下,它会影响DML操作的性能,最坏的情况下,它会导致数据损坏。这无疑会使我们的应用程序更加复杂

@trevorNorth在上下文方面提出了一个有效的观点。数据分布非常重要。T_目录中有多少行与该ID匹配?该结果集中有多少行与T_PERSON中的行匹配?这些实际值与解释计划中的基数匹配吗?如果不匹配,刷新数据库统计信息可能会允许数据库存储但如果你的统计数据是最新的,那么你需要一个不同的解决方案

比如…什么

调优是一项艰巨的任务,因为有太多的事情要考虑,具体的问题是很重要的。有些顾问在做其他事情的过程中,除了在其他人的代码中修复性能错误,做得很好。如果调整很简单,他们就无法做到这一点。 在缺乏确凿事实的情况下,以下是一些猜测。解决此问题的其他方法:

  • 通过构建复合索引,消除表读取,并可能获得哈希连接:
    T\u目录(ID,PERSONID,DIR\u ID)

    T\u PERSON(PERSONID,ID)
  • 在语句上构建快速刷新物化视图,并允许查询重写以满足查询
  • “我不得不对表格进行非规范化”

    在OLTP中,数据库去规范化总是一个坏消息。它会加快一些查询,但也会减慢其他查询的速度。最好的情况下,它会影响DML操作的性能,最坏的情况下,它会导致数据损坏。这无疑会使我们的应用程序更加复杂

    @trevorNorth在上下文方面提出了一个有效的观点。数据分布非常重要。T_目录中有多少行与该ID匹配?该目录中有多少行与该ID匹配