源码网资料下载:www.codepub.com 的数据量。比如使用IN操作符的子查询就经常需要物化,例如: SELECT * FROM ex1 WHERE ex1.a IN (SELECT b FROM ex2); 为了避免创建临时表,上面的查询可以写成:
SELECT * FROM ex1 WHERE EXISTS(SELECT 1 FROM ex2 WHERE ex2.b=ex1.a); SQLite 的较新版本(3.5.4及以后版本)会自动进行上述重写。 如果IN操作符的右手是值列表,如下: SELECT * FROM ex1 WHERE a IN (1,2,3);
列表值必须物化,因为会为这些值使用临时索引。也就是说上述语句相当于: SELECT * FROM ex1 WHERE a IN (SELECT 1 UNION ALL SELECT 2 UNION ALL SELECT 3);
当子查询出现在SELECT语句的FROM子句中时,也需要物化。例如: SELECT * FROM ex1 JOIN (SELECT b FROM ex2) AS t ON t.b=ex1.a; SQLite的优化器会将上述语句重写为:
SELECT ex1.*, ex2.b FROM ex1 JOIN ex2 ON ex2.b=ex1.a; (此处略去若干字)
9.1.6 瞬时索引(Transient Indices)
SQLite会使用瞬时索引来实现SQL语言的如下特色: ? ORDER BY或GROUP BY子句 ? 聚合查询中的DISTINCT保留字
? 被UNION、EXCEPT或INTERSECT结合起来的复合查询语句
每个瞬时索引存储在它们自己的临时文件中,当语句执行结束时被自动删除。
SQLite尽量用已存在的索引实现ORDER BY。但如果找不到合适的索引,SQLite就会将查询结果存储在瞬时索引中,其索引关键字就是ORDER BY的条目。在结果形成后,SQLite再回到瞬时索引的开始处,遍历并输出结果(已经是按需要的顺序保存了)。
SQLite实现GROUP BY的方法是将输出的记录按GROUP BY条目排序。每行都与前面一行进行比较看是否开始了一个新的\。按GROUP BY条目排序的方法与ORDER BY完全相同。SQLite尽量用已存在的索引实现,但如果没有合适的索引,就会创建瞬时索引。 (此处略去若干字)
9.1.7 VACUUM时使用的瞬时数据库(Transient Database)
VACUUM命令创建一个临时文件,并将数据库整个重建到该临时文件中。然后,临时文件的内容复制回原数据库文件中并将临时文件删除。
由VACUUM命令创建的临时文件仅在命令执行期间存在,大小不会超过原数据库。
9.2 编译期参数SQLITE_TEMP_STORE和Pragma
回卷日志、主日志和语句日志文件总是写到磁盘。但其它种类的临时文件可能只存储在内存中而永远不会写磁盘。这由编译期参数SQLITE_TEMP_STORE、temp_store pragma和临时下载源码就到源码网,www.codepub.com
源码网资料下载:www.codepub.com 文件的大小决定。 (此处略去若干字)
9.3 其它的临时文件优化
SQLite使用页缓冲区保存刚才读或写的数据库页。其实页缓冲区不仅被主数据库文件使用,还可以用做存储瞬时索引和临时文件中的表。即使SQLite设置这些内容是应该存储在磁盘上,其实刚开始时它们也都是存储在缓冲区中,在缓冲区满之前是不会写盘的。
这意味着很多情况下临时表或索引很小(缓冲区足以容纳),就没有临时文件创建,也就没有磁盘读写操作。
分配给临时表和索引的缓冲区空间大小由编译期参数SQLITE_DEFAULT_TEMP_CACHE_SIZE决定,默认值为500页。这个值在运行时不能修改。
源码网整理,www.codepub.com
下载源码就到源码网,www.codepub.com