2013-04-07 34 views
0

我有我目前定义如下的表:我应该使用多列索引还是两列1列?

CREATE TABLE pairs ( 
id INTEGER PRIMARY KEY, 
p1 INTEGER, 
p2 INTEGER, 
r INTEGER, 
UNIQUE(p1, p2) ON CONFLICT IGNORE, 
FOREIGN KEY (p1) REFERENCES points(id), 
FOREIGN KEY (p2) REFERENCES points(id) 
) 

之后,它填充有千兆字节的数据。现在我需要做很多选择的正是这样:

SELECT id, r FROM pairs WHERE p1 = 666 OR p2 = 666 

所以,问题是:我应该创建什么索引,以加快这一选择?

CREATE INDEX p1_index ON pairs(p1) 
CREATE INDEX p2_index ON pairs(p2) 

或可能

CREATE UNIQUE INDEX p_index ON pairs(p1, p2) 

或者甚至可能两者兼而有之? (并为他们购买新的硬盘)。 SQLite3不会自动为多列上的UNIQUE约束创建索引。

回答

2

由于您使用OR条件,我会去与多个索引。如果这是一个AND条件,那么多列索引会更好。

对于OR条件: 优化程序将开始查看其中一个索引,找到一个匹配并抓取该行。另一个索引只在与第一个索引不匹配时才被查看。 在多处理器系统上,两个索引都将(应该)并行扫描。太棒了,对吧?

对于AND条件: 如果有两个索引可用,优化器将不得不查看它们,合并两个索引扫描的输出,然后从基表中获取结果。这可能会变得很昂贵。在这里,多列索引本来就很棒。

但是,再次,优化器可能会根据可用的表和索引统计信息选择不同的路径。

希望这会有所帮助。

+0

不确定旧的sqlite3是否使用线程。 – 2013-04-07 08:18:29

+0

SQLite不使用线程。 – 2013-04-07 09:58:23

1

使用EXPLAIN QUERY PLAN检查是否使用索引。

为了您的示例查询,无论是单列索引将用于:

> EXPLAIN QUERY PLAN SELECT id, r FROM pairs WHERE p1 = 666 OR p2 = 666; 
0|0|0|SEARCH TABLE pairs USING INDEX p1_index (p1=?) (~10 rows) 
0|0|0|SEARCH TABLE pairs USING INDEX p2_index (p2=?) (~10 rows) 

多列索引(你已经因为独特的约束)将被使用,如果一个查询单记录需要两个柱:

> EXPLAIN QUERY PLAN SELECT id, r FROM pairs WHERE p1 = 666 AND p2 = 666; 
0|0|0|SEARCH TABLE pairs USING INDEX sqlite_autoindex_pairs_1 (p1=? AND p2=?) (~1 rows) 

然而,一个多列索引也可以用于查找它的第一列(或多个):

> DROP INDEX p1_index; 
> EXPLAIN QUERY PLAN SELECT id, r FROM pairs WHERE p1 = 666 OR p2 = 666; 
0|0|0|SEARCH TABLE pairs USING INDEX sqlite_autoindex_pairs_1 (p1=?) (~10 rows) 
0|0|0|SEARCH TABLE pairs USING INDEX p2_index (p2=?) (~10 rows) 

另请参阅文档:
Query Optimizer Overview,
Query Planning

+0

当我使用.indices查看我拥有的索引时,它显示主键列的自动索引,但没有UNIQUE约束的索引。我认为它只是在列描述中定义UNIQUE时才创建索引,而不是作为单独的语句。 – 2013-04-07 11:15:44

+0

'。indices'不显示内部索引(例如我的示例中的'sqlite_autoindex_pairs_1')。 – 2013-04-07 12:24:58

相关问题