小. 快速. 可靠.
选择任意三个.

Limits In SQLite

本文上下文中的"限制"表示不能超过的大小或数量. 我们关心的是诸如BLOB中最大字节数或表中最大列数之类的问题.

SQLite最初设计时应避免任意限制. 当然,在内存和磁盘空间有限的计算机上运行的每个程序都有某种限制. 但是在SQLite中,这些限制没有很好地定义. 策略是,如果它适合内存并且可以用32位整数进行计数,那么它应该可以工作.

不幸的是,无限制政策已经显示出会产生问题. 由于上限没有很好地定义,因此未进行测试,并且在将SQLite推向极限时经常发现错误. 因此,自3.5.8(2008-04-16)发行版以来的SQLite版本具有定义明确的限制,并且这些限制已作为测试套件的一部分进行了测试 .

This article defines what the limits of SQLite are and how they can be customized for specific applications. The default settings for limits are normally quite large and adequate for almost every application. Some applications may want to increase a limit here or there, but we expect such needs to be rare. More commonly, an application might want to recompile SQLite with much lower limits to avoid excess resource utilization in the event of bug in higher-level SQL statement generators or to help thwart attackers who inject malicious SQL statements.

某些限制可以在运行时使用sqlite3_limit()接口在每个连接的基础上更改,该接口具有为该接口定义的限制类别之一. 运行时限制是为具有多个数据库的应用程序设计的,其中一些仅供内部使用,而其他则可能受到潜在敌对的外部代理的影响或控制. 例如,Web浏览器应用程序可能使用内部数据库来跟踪历史页面浏览量,但是具有一个或多个单独的数据库,这些数据库由从互联网下载的javascript应用程序创建和控制. sqlite3_limit()接口允许不受信任代码管理的内部数据库不受约束,同时对不受信任的外部代码创建或控制的数据库设置严格的限制,以帮助防止拒绝服务攻击.

  1. 字符串或BLOB的最大长度

    SQLite中字符串或BLOB中的最大字节数由预处理器宏SQLITE_MAX_LENGTH定义. 该宏的默认值为10亿(10亿或1,000,000,000). 您可以使用以下命令行选项在编译时提高或降低该值:

    -DSQLITE_MAX_LENGTH=123456789

    当前实现仅支持最大2 31 -1或2147483647的字符串或BLOB长度.某些内置函数(例如hex())可能在此之前就失败了. 在对安全性敏感的应用程序中,最好不要尝试增加最大字符串和blob长度. 实际上,如果可能的话,最好将最大字符串长度和blob长度减小到几百万.

    在SQLite的INSERT和SELECT处理的一部分期间,数据库中每一行的全部内容被编码为单个BLOB. 因此,SQLITE_MAX_LENGTH参数还确定一行中的最大字节数.

    可以使用sqlite3_limit (db, SQLITE_LIMIT_LENGTH ,size)接口在运行时减小最大字符串或BLOB长度.

  2. 最大列数

    SQLITE_MAX_COLUMN编译时参数用于设置以下项的上限:

    SQLITE_MAX_COLUMN的默认设置为2000.您可以在编译时将其更改为最大为32767的值.另一方面,许多经验丰富的数据库设计人员都会认为,规范化的数据库在一个表中最多不需要100列.

    在大多数应用程序中,列数很少-几十列. SQLite代码生成器中的某些地方使用的算法是O(N²),其中N是列数. 因此,如果将SQLITE_MAX_COLUMN重新定义为一个非常大的数字,并且生成使用大量列的SQL,则可能会发现sqlite3_prepare_v2()运行缓慢.

    使用sqlite3_limit (db, SQLITE_LIMIT_COLUMN ,size)接口可以在运行时降低最大列数.

  3. SQL语句的最大长度

    SQL语句文本中的最大字节数限制为SQLITE_MAX_SQL_LENGTH,默认值为1000000.您可以将该限制重新定义为与SQLITE_MAX_LENGTH和1073741824中的较小者一样大.

    如果一个SQL语句的长度限制为一百万个字节,那么很显然,您无法通过将它们作为文字嵌入到INSERT语句中来插入数百万个字节的字符串. 但是无论如何,您都不应这样做. 对数据使用主机参数 . 准备如下的简短SQL语句:

    插入tab1值(?,?,?);

    然后,使用sqlite3_bind_XXXX()函数将较大的字符串值绑定到SQL语句. 绑定的使用消除了对字符串中的引号字符进行转义的需要,从而降低了SQL注入攻击的风险. 由于不需要分析或复制大字符串,因此它也运行得更快.

    可以在运行时使用sqlite3_limit (db, SQLITE_LIMIT_SQL_LENGTH ,size)接口降低SQL语句的最大长度.

  4. 联接中的最大表数

    SQLite不支持包含超过64个表的联接. 此限制是由于SQLite代码生成器使用位图而在查询优化器中每个连接表使用一位的事实引起的.

    SQLite使用高效的查询计划程序算法 ,因此甚至可以快速准备大型联接. 因此,没有机制可以提高或降低联接中表数量的限制.

  5. 表达式树的最大深度

    SQLite将表达式解析为树以进行处理. 在代码生成期间,SQLite递归地遍历此树. 因此,表达式树的深度受到限制,以避免使用过多的堆栈空间.

    SQLITE_MAX_EXPR_DEPTH参数确定最大表达式树深度. 如果该值为0,则不强制执行任何限制. 当前实现的默认值为1000.

    如果SQLITE_MAX_EXPR_DEPTH最初为正,则可以在运行时使用sqlite3_limit (db, SQLITE_LIMIT_EXPR_DEPTH ,size)接口降低表达式树的最大深度. 换句话说,如果表达式深度已经存在编译时限制,则可以在运行时降低最大表达式深度. 如果在编译时将SQLITE_MAX_EXPR_DEPTH设置为0(如果表达式的深度不受限制),则sqlite3_limit (db, SQLITE_LIMIT_EXPR_DEPTH ,size)为空.

  6. 函数的最大参数个数

    SQLITE_MAX_FUNCTION_ARG参数确定可以传递给SQL函数的最大参数数量. 此限制的默认值为100.SQLite应该与具有数千个参数的函数一起使用. 但是,我们怀疑有人试图使用多个参数来调用函数,实际上是在尝试使用SQLite的系统中发现安全漏洞,而没有做有用的工作,因此出于这个原因,我们将此参数设置得相对较低.

    函数参数的数量有时存储在带符号的字符中. 因此,SQLITE_MAX_FUNCTION_ARG的上限为127.

    可以在运行时使用sqlite3_limit (db, SQLITE_LIMIT_FUNCTION_ARG ,size)接口降低函数中参数的最大数量.

  7. 复合SELECT语句中的最大术语数

    复合SELECT语句是通过运算符UNION,UNION ALL,EXCEPT或INTERSECT连接的两个或多个SELECT语句. 我们将复合SELECT中的每个单独的SELECT语句称为"项".

    SQLite中的代码生成器使用递归算法处理复合SELECT语句. 为了限制堆栈的大小,因此我们限制了复合SELECT中的项数. 条款的最大数量是SQLITE_MAX_COMPOUND_SELECT,默认值为500.我们认为这是一个慷慨的分配,因为在实践中,我们几乎从来没有看到复合选择中条款的数量超过个位数.

    可以在运行时使用sqlite3_limit (db, SQLITE_LIMIT_COMPOUND_SELECT ,size)接口降低复合SELECT术语的最大数量.

  8. LIKE或GLOB模式的最大长度

    对于某些病理情况,SQLite的默认LIKEGLOB实现中使用的模式匹配算法可以表现出O(N²)性能(其中N是模式中的字符数). 为了避免能够指定自己的LIKE或GLOB模式的恶意者进行的拒绝服务攻击,LIKE或GLOB模式的长度限制为SQLITE_MAX_LIKE_PATTERN_LENGTH字节. 此限制的默认值为50000.现代工作站甚至可以相对快速地评估甚至是50000字节的病理LIKE或GLOB模式. 仅当模式长度达到数百万个字节时,拒绝服务问题才起作用. 但是,由于最有用的LIKE或GLOB模式的长度最多为几十个字节,因此如果他们知道外部用户能够生成任意模式,那么偏执的应用程序开发人员可能希望将此参数减小到几百个范围.

    可以使用sqlite3_limit (db, SQLITE_LIMIT_LIKE_PATTERN_LENGTH ,size)接口在运行时降低LIKE或GLOB模式的最大长度.

  9. 单个SQL语句中的最大主机参数数

    主机参数是使用sqlite3_bind_XXXX()接口之一填充的SQL语句中的占位符. 许多SQL程序员熟悉使用问号("?")作为主机参数. SQLite还支持以":"," $"或" @"开头的命名主机参数以及形式为"?123"的带编号主机参数.

    SQLite语句中的每个主机参数都分配有一个数字. 数字通常以1开头,每个新参数增加1. 但是,使用"?123"形式时,主机参数编号是问号后的编号.

    SQLite allocates space to hold all host parameters between 1 and the largest host parameter number used. Hence, an SQL statement that contains a host parameter like ?1000000000 would require gigabytes of storage. This could easily overwhelm the resources of the host machine. To prevent excessive memory allocations, the maximum value of a host parameter number is SQLITE_MAX_VARIABLE_NUMBER, which defaults to 999 for SQLite versions prior to 3.32.0 (2020-05-22) or 32766 for SQLite versions after 3.32.0.

    可以在运行时使用sqlite3_limit (db, SQLITE_LIMIT_VARIABLE_NUMBER ,size)接口降低最大主机参数数.

  10. 触发递归的最大深度

    SQLite限制了触发器的递归深度,以防止涉及递归触发器的语句使用无限制的内存量.

    在SQLite 3.6.18 (2009-09-11)之前,触发器不是递归的,因此此限制毫无意义. 从3.6.18版本开始,支持递归触发器,但必须使用PRAGMA recursive_triggers语句显式启用它. 从版本3.7.0 (2009-09-11)开始,默认情况下启用了递归触发器,但可以使用PRAGMA recursive_triggers手动禁用它. 仅当启用了递归触发器时,SQLITE_MAX_TRIGGER_DEPTH才有意义.

    默认的最大触发器递归深度为1000.

  11. 最大连接数据库数

    ATTACH语句是一个SQLite扩展,它允许将两个或多个数据库关联到同一数据库连接,并且可以像对待单个数据库一样进行操作. 同时连接的数据库数限制为SQLITE_MAX_ATTACHED,默认情况下设置为10. 附加数据库的最大数量不能增加到125以上.

    可以在运行时使用sqlite3_limit (db, SQLITE_LIMIT_ATTACHED ,size)接口降低附加数据库的最大数量.

  12. 数据库文件中的最大页数

    SQLite能够限制数据库文件的大小,以防止数据库文件变得太大而占用过多的磁盘空间. SQLITE_MAX_PAGE_COUNT参数通常设置为1073741823,它是单个数据库文件中允许的最大页数. 尝试插入新数据将导致数据库文件大于该数据的尝试将返回SQLITE_FULL.

    SQLITE_MAX_PAGE_COUNT的最大可能设置为2147483646.当使用最大页面大小为65536时,这将使最大SQLite数据库大小约为140 TB.

    max_page_count PRAGMA可用于在运行时提高或降低此限制.

  13. 表中的最大行数

    表中的理论最大行数为2 64 (18446744073709551616或大约1.8e + 19). 由于将首先达到140 TB的最大数据库大小,因此无法达到此限制. 一个140 TB的数据库最多可以容纳大约1e + 13行,然后只有在没有索引并且每行包含的数据很少的情况下才可以.

  14. 最大数据库大小

    每个数据库都包含一个或多个"页面". 在单个数据库中,每个页面的大小都是相同的,但是不同的数据库可以具有的页面大小是512到65536(含)之间的2的幂. 数据库文件的最大大小为2147483646页. 在最大页面大小为65536字节的情况下,这将转换为大约1.4e + 14字节的最大数据库大小(140 TB或128 TB,或140,000 GB或128,000 GI).

    由于开发人员无法访问能够达到此限制的硬件,因此未测试此特定上限. 但是,测试可以验证SQLite在数据库达到基础文件系统的最大文件大小(通常比理论上的最大数据库大小小得多)时以及数据库由于磁盘空间耗尽而无法增长时正确且合理地运行.

  15. 架构中的最大表数

    每个表和索引在数据库文件中至少需要一页. 前一句中的"索引"是指使用CREATE INDEX语句显式创建的索引或由UNIQUE和PRIMARY KEY约束创建的隐式索引. 由于数据库文件中的最大页面数为2147483646(略高于20亿),因此这也是架构中表和索引数的上限.

    Whenever a database is opened, the entire schema is scanned and parsed and a parse tree for the schema is held in memory. That means that database connection startup time and initial memory usage is proportional to the size of the schema.

by  ICOPY.SITE