9

我真的需要update使用对数函数对超过 400,000 行执行一次。不幸的是,sqlite 中似乎不存在 SQL 对数函数。有什么方法可以导出对数函数或导入LOG函数?

我知道如何做到这一点的唯一另一种方法是我相信通过 python 订购 O(n^2) 。这种方法将花费太长时间(我尝试过,在我的慢速计算机上完成 6% 需要大约 1.5 小时)。

编辑:

我也发现了为什么花了这么长时间。数据库中的主键未标记为主键。所以我使用的代码如下:

for row in database:
    ...calculations for the row...
    ...sql update for the specific row which follows:...
    for search_row in database:
        if search_row[id] = row[id]:
            ...update values here...

令人难以置信的低效... O(n^2)

4

5 回答 5

7

没有内置对数函数;您必须定义自己的功能。

如果您使用的是 Python,则可以同时使用pysqliteAPSW模块。

于 2013-01-27T20:41:10.080 回答
3

事实证明,数学函数(包括对数)是在 Sqlite 中实现的,但在 Ubuntu 上的标准 Sqlite 编译中被禁用。为了启用它们,您应该从这里下载 Sqlite 源代码(“获取代码”)并根据说明进行编译(“编译”)。默认情况下将启用必要的选项-DSQLITE_ENABLE_MATH_FUNCTIONS 。编译后,您将sqlite3在构建目录中获得可执行文件,这应该作为本地文件运行:

$ ./sqlite3 <database-file>

在编译之前,我建议安装readline,以便历史浏览(箭头)和自动完成在 Sqlite 命令行中正常工作。

sudo apt install libreadline-dev
于 2021-01-05T12:02:59.840 回答
1

是什么让你认为它会是O(n^2)?如果有的话,它应该是线性的:O(n).

如果您使用自动提交模式,这几乎是它如此缓慢的唯一原因 - 这将导致 SQLite 在每次更新时将缓冲区刷新到磁盘。

如果你开始事务,然后使用 SELECT / UPDATE 循环,最后提交,你的更新应该很快(前提是你的对数函数不是很慢)。

于 2013-01-27T20:44:35.450 回答
1

那些只需要它进行低精度的自然排序(小数后一位小数,并且只精确到小数点后 4 位)但性能良好的人可以使用:

( (length(count(*) * 1000 / 1000) + length(count(*) * 1258 / 1000) + length(count(*) * 1584 / 1000) + length(count(*) * 1995 / 1000) + length(count(*) * 2511 / 1000) + length(count(*) * 3162 / 1000) + length(count(*) * 3981 / 1000) + length(count(*) * 5011 / 1000) + length(count(*) * 6309 / 1000) + length(count(*) * 7943 / 1000)) / 10.0 - 1.0 )

我在一个连接中需要它,我对连接的 n:m 表中的条目数的日志感兴趣,因此我使用了“count(*)”,我计算了它的对数。

... ( ( ( ( (0.0 + length(count(*) * 1000 / 1000) + length(count(*) * 1258 / 1000) + length(count(*) * 1584 / 1000) + length(count(*) * 1995 / 1000) + length(count(*) * 2511 / 1000) + length(count(*) * 3162 / 1000) + length(count(*) * 3981 / 1000) + length(count(*) * 5011 / 1000) + length(count(*) * 6309 / 1000) + length(count(*) * 7943 / 1000)) / 10.0 - 1.0 ) * 10 +1 ) + ( IFNULL(stat.sum * 1.0 / (1848) , 0.9999999) ) ) / ( IFNULL(stat.count,1) + ( ( (0.0 + length(count(*) * 1000 / 1000) + length(count(*) * 1258 / 1000) + length(count(*) * 1584 / 1000) + length(count(*) * 1995 / 1000) + length(count(*) * 2511 / 1000) + length(count(*) * 3162 / 1000) + length(count(*) * 3981 / 1000) + length(count(*) * 5011 / 1000) + length(count(*) * 6309 / 1000) + length(count(*) * 7943 / 1000)) / 10.0 - 1.0 ) *10 +1 ) ) ) as rating, stat.expl as expl from ...

可以使用任何其他整数变量代替 'count(*)',只要确保它是整数,或者将其转换为整数。浮动的长度显然对你没有任何好处。

这是一个肮脏的技巧,它使用了一个事实,即 int 的十进制表示的字符串的长度由对数定义,并提取它。但是与计算浮点数的所有数字的对数实现相比,将 int 转换为字符串并计算长度似乎是相当有效的,除了精度只有一位小数的缺点。我能用可移植的 sqlite 语法做的最好。

PS:如果有人对如何提高精度、性能或具有可变对数基数有任何想法(而不是将其固定为以 10 为基数的第一个小数位),请发表评论。

PPS:http ://sqlfiddle.com/#!7/9aadc/2/0

于 2021-10-10T21:41:34.177 回答
-1

使用log10(number)功能。

对于反日志,使用power(10, number)函数。

于 2019-05-12T13:11:38.643 回答