有效地选择数据sql

时间:2010-05-27 06:13:53

标签: sql oracle performance

我有一个非常大的表,有超过1000条记录和200列。当我尝试使用WHERE语句检索匹配SELECT子句中某些条件的记录时,需要花费很多时间。但大多数时候我只想选择一个与WHERE子句中的条件匹配的记录而不是所有记录。

我想应该有一种方法可以选择一个记录并退出,这将最大限度地缩短检索时间。我在ROWNUM=1子句中尝试了WHERE,但它确实没有用,因为我猜即使找到符合WHERE条件的第一条记录后,引擎仍会检查所有记录。如果我只想选择几条记录,是否有优化方法? 提前致谢。

修改

我正在使用oracle 10g。 查询看起来像,

Select * 
from Really_Big_table 
where column1 is NOT NULL 
and column2 is NOT NULL 
and rownum=1;

这似乎比没有rownum = 1;

的版本慢

5 个答案:

答案 0 :(得分:1)

rownum是您想要的,但您需要将主查询作为子查询执行。

例如,如果您的原始查询是:

  SELECT co1, col2
    FROM table
    WHERE condition

然后你应该尝试

  SELECT *
  FROM (
    SELECT col1, col2
      FROM table
      WHERE condition
  ) WHERE rownum <= 1

有关rownum如何在Oracle中运行的详细信息,请参阅http://www.oracle.com/technology/oramag/oracle/06-sep/o56asktom.html

答案 1 :(得分:1)

1,000条记录不是表格中的大量数据。 200列是一个相当宽的表。出于这个原因,我建议你不要处理一个非常大的表 - 我已经对数百万行执行了查询而没有任何问题。

这是一个小实验......与“SELECT *”查询相比,运行此操作需要多长时间?

SELECT
    Really_Big_table.Id
FROM
    Really_Big_table
WHERE 
    column1 IS NOT NULL
AND
    column2 IS NOT NULL
AND
    rownum=1;

答案 2 :(得分:0)

在SQL中,大多数优化都会以表格上的索引形式出现(您可以将WHEREORDER BY列中显示的列编入索引作为粗略指南。

您没有指定您正在使用的SQL数据库,因此我无法指向一个好的资源。

Here是对Oracle索引的介绍。

Here另一个教程。

对于查询 - 您应始终指定要返回的列,而不是使用毯子*

答案 3 :(得分:0)

示例如下:您可以查看更多here

SELECT ename, sal 
FROM ( SELECT ename, sal, RANK() OVER (ORDER BY sal DESC) sal_rank
              FROM emp ) 
WHERE sal_rank <= 1;

您还必须对WHERE子句中的列进行一些列索引

答案 4 :(得分:0)

查询1000行表不应该花费很多时间。但也有例外情况,请检查您是否遇到以下情况之一:

1。删除了很多行

这张桌子过去有很多行。由于高水位线( HWM )仍然很高(删除不会降低它)并且FULL TABLE SCAN读取所有数据直到高水位线,可能需要很长时间即使表现在几乎为空,也返回结果。

分析您的表格(dbms_stats.gather_table_stats('<owner>','<table>'))并将行实际使用的空间(磁盘空间)与有效空间(数据)进行比较,例如:

SELECT t.avg_row_len * t.num_rows data_bytes, 
       (t.blocks - t.empty_blocks) * ts.block_size bytes_used
  FROM user_tables t
  JOIN user_tablespaces ts ON t.tablespace_name = ts.tablespace_name
 WHERE t.table_name = '<your_table>';

您必须考虑行和块的开销以及为更新保留的空间(PCT_FREE)。如果您发现使用的空间比需要的多得多(典型开销低于30%,YMMV),您可能需要重置HWM:

  • ALTER TABLE <your_table> MOVE;然后重建INDEX(ALTER INDEX <index> REBUILD),不要忘记之后收集统计数据。
  • 使用DBMS_REDEFINITION

2。该表有非常大的列

检查是否有数据类型为LOB,CLOB,LONG(irk)等的列。任何这些列中超过4000字节的数据都存储在行外(在单独的段中),这意味着如果不这样做选择这些列,您只需查询其他较小的列。

如果您遇到这种情况,请不要使用SELECT *。要么您不需要大列中的数据,要么使用SELECT rowid然后再进行第二次查询:SELECT * WHERE rowid = <rowid>