9

update対数関数を使用して、40万行を超える行を実行する必要があります。残念ながら、SQLの対数関数はsqliteに存在しないようです。対数関数を導出したり、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を使用している場合、これはpysqliteモジュールとAPSWモジュールの両方可能です

于 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はすべてのUPDATEでバッファをディスクにフラッシュします。

トランザクションを開始し、SELECT / UPDATEループを使用し、最後にコミットすると、更新は非常に高速になります(対数関数がそれほど遅くない場合)。

于 2013-01-27T20:44:35.450 に答える
1

精度が低く(小数部の小数点以下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の10進表現の文字列の長さが対数で定義されているという事実を使用して、それを抽出するという汚いトリックです。しかし、floatのすべての桁を計算するlogorithm実装と比較すると、整数から文字列への変換と長さのカウントは、小数点以下1桁しかないという欠点を除けば、かなり効率的であるように思われます。ポータブルsqlite構文でできる最善のこと。

PS:精度、パフォーマンスを改善する方法、または可変対数ベース(10を底とする小数点以下第1位に切り捨てられるように固定されるのではなく)を使用する方法について誰かがアイデアを持っている場合は、コメントしてください。

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 に答える