「リクエスト内の配布」または「検索を削除する」

良いバストはバストの不足です。 完全な列挙をクエリで置き換える例を考えてみましょう。



かつて約3年前に、1C構成を最適化し、ある会社のボトルネックを解消することが必要になりました。 これらのボトルネックの1つは、商品を直列に配布するための、一見無害なメカニズムであることが判明しました。 一番下の行は、多くの行が分散され、非常に遅いということです。 もちろん、一度に数百万ではありませんが、この1つのドキュメントの配布には最大1分かかります。



T-SQLのクエリを具体的に引用します。 Khabravtsamに近いと思います。



一般的に、このビジネスは誰もが非常に悲しくなりました。 同時に、会計士は文書を転送し、他のオペレーターも出荷文書を作成し、「大きな」クライアントが出荷されると、しばらくの間凍結しました。



ちなみに、当時の2〜3年間の1Cデータベースのサイズは最大500 GBで、1日1クライアントから1ダースまたは2オーダーの注文があり、一部のクライアントでは1000を超えることがありました。 「1000行あたり-これは超自然的なことではありません。 インデックスの再作成、統計の更新、縮小、およびその他の必要な手順が定期的に実行されましたが、これはそれについてではありません。 最適化オブジェクトに戻りましょう。 当時、配布メカニズムは簡単でした:



  1. 要求は、連続して残高を受け取りました(命名法-シリーズ-数量)。
  2. 別のリクエストにより、出荷用の商品表(命名法-バイヤーの注文-数量)を受け取りました。
  3. これまでのところ、 配布数 > 0 サイクル ..........」という原則に従って、各アイテムを徹底的に検索しました。


なぜなら 私は常に、大量のデータの列挙という事実自体がすでにボトルネックであるという立場を維持してきましたが、列挙アルゴリズムを「改善する」可能性を考慮することすら考えていませんでした。 代替手段が必要でした。 また、そのとき、私はすでに長い間複雑なクエリを最適化することに手を取り、クエリだけでは解決できない単一の問題はなく、99%のケースで高品質のクエリ(クエリパケット)が最も効果的なソリューションであると確信していましたクエリ結果の後処理よりも。 問題はこの解決策を見つけることだけでした。



私は問題のためにかなり些細な条件でスモークブレイクに出かけました(1つのテーブルの次元で数量を別のテーブルの数量で分配する)と2つの論文:





そして、まさにこの瞬間に、私が精神的に2番目の論文である「 もっと 」という言葉を話して、私に決断を促しました。 さらに、雪の中で棒を使って描くと、クエリコンソールで仮説を試すために実行した方法を文書化する時間がありませんでした。

次の簡単な例を考えてみましょう。



商品の量を片側に配置した保管セル(A、B、C、D)と商品自体(X、Y、Z)があり、これらのセルに「ソート」する必要がありますが、セル内に場所があるよりも多くの商品をセルに入れませんでした。



A-10か所

B-1位

C-5か所

D-8か所



X-13個

Y-1個

Z-4個


結果は、分布表になります。



x-10

Bx-1

Cx-2

CY-1

Cz-2

Dz-2


これを行うには、配信順序を決定する必要があります。これは、これを行うのに十分なほど簡単であることが判明しました。



select t1.Cell, t1.Qty, ISNULL(sum(t2.Qty),0)+1 as OrderBottom, ISNULL(sum(t2.Qty),0)+t1.Qty as OrderTop into OrderedCells from Cells as t1 left join Cells as t2 on t1.Cell > t2.Cell Group by t1.Cell, t1.Qty
      
      





ちなみに、ここでは、たとえば商品を最初にいくつかのセルに配置する必要がある場合、配送順序を考慮することもできます。 接続の条件を変更することで解決します。



商品と同じこと:



 select t1.Goods, t1.Qty, ISNULL(sum(t2.Qty),0)+1 as OrderBottom, ISNULL(sum(t2.Qty),0)+t1.Qty as OrderTop into OrderedGoods from Goods as t1 left join Goods as t2 on t1.Goods > t2.Goods Group by t1.Goods, t1.Qty
      
      





理解を容易にするために、これらのすべての位置をテーブル内のピースごとに分解し、分布の順序で上下に重ねます。



画像



境界条件を記述するだけです。 そして、これらのテーブルを結合して結果を取得するだけです。



 select OrderedCells.Cell, OrderedGoods.Goods, case when OrderedGoods.OrderTop < OrderedCells.OrderTop then OrderedGoods.OrderTop else OrderedCells.OrderTop end - case when OrderedGoods.OrderBottom > OrderedCells.OrderBottom then OrderedGoods.OrderBottom else OrderedCells.OrderBottom end + 1 as Qty from OrderedCells inner join OrderedGoods on OrderedCells.OrderBottom <= OrderedGoods.OrderTop and OrderedCells.OrderTop >= OrderedGoods.OrderBottom
      
      





リクエストで、必要以上のフィールドが意図的に追加される予約をすぐに行います。 1つの分布境界(累積)で対処し、「+ 1」を作成することはできませんが、私には思われたように、この形式では理解がより明白です。 このスレッドではクエリの最適化を考慮していないため、ここでもインデックスについては説明しません。 さて、より複雑な分布アルゴリズム(たとえば、複数の次元)は、接続の条件を変更して境界をチェックすることによってのみ解決されます。



以上です。 その結果、同じデータボリュームで数分間待機する代わりに、このリクエストは数ミリ秒で実行されました。



この記事の歌詞が豊富であることをおpoびします。 私は狭い問題の数学的な解決策ではなく、そのような問題を解決するための概念的アプローチ、つまり私の思考の道筋を共有したかったのです。



All Articles