昨年が終わったちょうどその時、PostGISジオメトリ計算を含む彼らの長年のPostgreSQLクエリの1つが特定の値に対してはるかに遅いので、私たちの長年の顧客の1人が私たちに来ました。私たちは問題を調査し、それを解決する方法を見つけました。読む!問題の原因として私たちが見つけたものはあなたを驚かせるでしょう!
お客様から報告された最初の観察は、ST_DistanceSpheroid
を含むクエリを実行することでした。 POINT(33.681953 23.155994)
に距離を返すように求められたときに約7ミリ秒かかりました 特定の回転楕円体上にありますが、そのポイントがPOINT(33.681953 23.1559941)
に移動された場合 (0.0000001
だけの違い )その後、0.13ミリ秒かかりました。 60倍速い!地球上で(別の回転楕円体!)何が起こっている可能性がありますか?
当初、テスト環境での速度低下を再現することはできませんでした。私たちの手では、両方のクエリが同じように速く実行され、速度が低下することはありません。更新が必要になる可能性があると考えて、使用中のソフトウェアの特定のバージョンを掘り下げました。お客様から報告されたバージョンを使用しました:PostgreSQL 10.11、PostGIS 2.4.4、libproj4.93。それらの正確なバージョンにダウングレードすることで洞窟時代に戻りましたが、成功しませんでした。
やがて、お客様がUbuntu 18.04を使用していることに気づいたので、それを試してみました…そして、見よ、問題はそこで再現されました。そのマシンでクエリをプロファイリングする機会に飛びついたと言えば十分です。これを入手しました:
Samples: 224K of event 'cpu-clock', Event count (approx.): 56043500000 Children Self Command Shared Object Symbol + 84.86% 0.00% postgres [unknown] [.] 0xffffffffffffffff + 84.59% 0.00% postgres postgres [.] DirectFunctionCall4Coll + 84.58% 0.00% postgres postgis-2.5.so [.] geometry_distance_spheroid + 84.56% 0.00% postgres liblwgeom-2.5.so.0.0.0 [.] lwgeom_distance_spheroid + 84.31% 0.19% postgres libm-2.27.so [.] __sincos + 84.18% 0.00% postgres libm-2.27.so [.] __cos_local (inlined) + 84.13% 0.00% postgres libm-2.27.so [.] cslow2 (inlined) + 84.05% 0.01% postgres libm-2.27.so [.] __mpcos + 83.95% 0.32% postgres libm-2.27.so [.] __c32 + 83.87% 0.00% postgres postgres [.] ExecInterpExpr + 83.75% 0.00% postgres postgres [.] standard_ExecutorRun + 83.75% 0.00% postgres postgres [.] ExecutePlan (inlined) + 83.73% 0.00% postgres postgres [.] ExecProcNode (inlined) + 83.73% 0.00% postgres postgres [.] ExecScan + 83.67% 0.00% postgres postgres [.] ExecProject (inlined) + 83.67% 0.00% postgres postgres [.] ExecEvalExprSwitchContext (inlined) + 83.65% 0.00% postgres postgres [.] _SPI_execute_plan + 83.60% 0.00% postgres postgres [.] _SPI_pquery (inlined) + 83.49% 0.01% postgres plpgsql.so [.] exec_stmts + 83.49% 0.00% postgres plpgsql.so [.] exec_stmt (inlined) + 83.49% 0.00% postgres plpgsql.so [.] exec_stmt_fori (inlined) + 83.48% 0.00% postgres plpgsql.so [.] exec_stmt_perform (inlined) + 83.48% 0.00% postgres plpgsql.so [.] exec_run_select + 83.47% 0.00% postgres postgres [.] SPI_execute_plan_with_paramlist + 81.67% 0.01% postgres liblwgeom-2.5.so.0.0.0 [.] edge_distance_to_point + 81.67% 0.00% postgres liblwgeom-2.5.so.0.0.0 [.] 0x00007f2ce1c2c0e6 + 61.85% 60.82% postgres libm-2.27.so [.] __mul + 54.83% 0.01% postgres liblwgeom-2.5.so.0.0.0 [.] sphere_distance + 27.14% 0.00% postgres plpgsql.so [.] exec_stmt_block + 26.67% 0.01% postgres liblwgeom-2.5.so.0.0.0 [.] geog2cart + 19.24% 0.00% postgres libm-2.27.so [.] ss32 (inlined) + 18.28% 0.00% postgres libm-2.27.so [.] cc32 (inlined) + 12.55% 0.76% postgres libm-2.27.so [.] __sub + 11.46% 11.40% postgres libm-2.27.so [.] sub_magnitudes + 8.15% 4.89% postgres libm-2.27.so [.] __add + 4.94% 0.00% postgres libm-2.27.so [.] add_magnitudes (inlined) + 3.18% 3.16% postgres libm-2.27.so [.] __acr + 2.66% 0.00% postgres libm-2.27.so [.] mcr (inlined) + 1.44% 0.00% postgres liblwgeom-2.5.so.0.0.0 [.] lwgeom_calculate_gbox_geodetic + 1.44% 0.00% postgres liblwgeom-2.5.so.0.0.0 [.] ptarray_calculate_gbox_geodetic
ジブリッシュ、あなたは言います。ただし、このプロファイルには非常に興味深いものがあります…最初の26行を無視して、 __ mulに焦点を当てる必要があります。 そこに並んでください。 「自己」時間の60.82%がわかりますか? (私はあなたの心がちょうど作った実現の音を聞くことができます)。では、なぜ回転楕円体の特定のポイントに時間がかかり、他のポイントには時間がかからないのでしょうか。また、Ubuntu 18.04では時間がかかるのに、他のマシンでは時間がかからないのはなぜですか? PostGISをアップグレードしても問題が解決しないのはなぜですか?
明らかなことを理解すると、答えが提案されました。PostGISはlibm
を呼び出すことで、多くの三角法(正弦、余弦、接線など)を実行します。 関数。 glibcの変更ログを見ると、三角関数にいくつかの最適化があります。特定の入力の場合、三角関数の計算では、他の入力には使用できないショートカットが使用されます。そして、そのようなショートカットは時間とともに最適化されてきました。実際、glibcは、2.27と2.29の両方について、正弦/余弦/etc関数の最適化について言及していることを発表しています。どうやら、かつては非常に正確な結果を提供するはずのIntelによるいくつかの最適化がありましたが、その後誰かが精度の主張が正しくないことに気づいたので、glibcはそれらの最適化の使用を無効にしました。後で、そのようなものは別の、しかし再び速い方法で再実装されました。またはそのようなもの—私のような部外者にとって、正確な詳細を理解するのは難しいです。
新しいバージョンのglibcにアップグレードすると問題が解決し、他のすべては同じままになると思われました。私たちの顧客はそれを試しました、そして確かにそれは真実でした、そして彼らは幸せでした。 どれかはよくわかりません これらのglibcの変更のうち、原因となったものが1つあります。それは、常に最新のソフトウェアで実行することをお勧めします。
にじみが鋭いことを覚えておいてください…だから気をつけてください。