在我们的产品中,我们有一个通用的搜索引擎,并试图优化搜索性能。查询中使用的许多表都允许空值。我们是否应该重新设计我们的表,以禁止空值用于优化?
我们的产品既可以在Oracle
上运行,也可以在MS SQL Server
上运行。
发布于 2009-06-19 10:24:46
在Oracle
中,NULL
值没有索引,即这个查询:
SELECT *
FROM table
WHERE column IS NULL
将始终使用全表扫描,因为索引不会覆盖所需的值。
更重要的是,这个查询:
SELECT column
FROM table
ORDER BY
column
出于同样的原因,还将使用全表扫描和排序。
如果您的值本质上不允许NULL
,则将该列标记为NOT NULL
。
发布于 2009-06-19 10:15:54
简短的回答:是的,有条件的!
空值和性能的主要问题是与正向查找有关。
如果您在表中插入一行,并使用空值,那么它将被放在它所属的自然页中。任何查找该记录的查询都会在适当的位置找到它。到目前为止很简单……
...but假设页面已填满,现在该行被夹在其他行中。仍然进展顺利..。
...until行被更新,并且空值现在包含一些内容。行的大小已经超出了它可以使用的空间,所以DB引擎必须对其采取一些措施。
服务器执行的最快的操作是将行从该页移到另一页,并用前向指针替换该行的条目。不幸的是,这需要在执行查询时进行额外的查找:一个查找行的自然位置,另一个查找行的当前位置。
所以,对你的问题的简短回答是肯定的,使这些字段不可为空将有助于提高搜索性能。如果经常发生您搜索的记录中的空字段被更新为非空字段的情况,这一点尤其正确。
当然,还有其他与大型数据集相关的损失(特别是I/O,尽管索引深度很小),而且在概念上需要空值的字段中不允许出现空值,这会导致应用程序出现问题,但嘿,这是另一个问题:)
发布于 2009-06-20 09:07:39
这是一个额外的答案,以引起人们对David Aldridge对Quassnoi接受的答案的评论的额外关注。
声明:
此查询:
SELECT * FROM表WHERE column为空
将始终使用全表扫描
不是真的。以下是使用带有文字值的索引的计数器示例:
SQL> create table mytable (mycolumn)
2 as
3 select nullif(level,10000)
4 from dual
5 connect by level <= 10000
6 /
Table created.
SQL> create index i1 on mytable(mycolumn,1)
2 /
Index created.
SQL> exec dbms_stats.gather_table_stats(user,'mytable',cascade=>true)
PL/SQL procedure successfully completed.
SQL> set serveroutput off
SQL> select /*+ gather_plan_statistics */ *
2 from mytable
3 where mycolumn is null
4 /
MYCOLUMN
----------
1 row selected.
SQL> select * from table(dbms_xplan.display_cursor(null,null,'allstats last'))
2 /
PLAN_TABLE_OUTPUT
-----------------------------------------------------------------------------------------
SQL_ID daxdqjwaww1gr, child number 0
-------------------------------------
select /*+ gather_plan_statistics */ * from mytable where mycolumn
is null
Plan hash value: 1816312439
-----------------------------------------------------------------------------------
| Id | Operation | Name | Starts | E-Rows | A-Rows | A-Time | Buffers |
-----------------------------------------------------------------------------------
| 0 | SELECT STATEMENT | | 1 | | 1 |00:00:00.01 | 2 |
|* 1 | INDEX RANGE SCAN| I1 | 1 | 1 | 1 |00:00:00.01 | 2 |
-----------------------------------------------------------------------------------
Predicate Information (identified by operation id):
---------------------------------------------------
1 - access("MYCOLUMN" IS NULL)
19 rows selected.
正如您所看到的,索引正在使用中。
问候你,罗伯。
https://stackoverflow.com/questions/1017239
复制相似问题