この質問は、実際には、データモデルが1つにまとめられた一連の問題です。それらを1つずつ解き始める必要があります。パズルの各ピースを単純化しようとすると、より自然で直感的なソリューションがドロップアウトします。
問題1:DBの順序に依存できない
データの並べ替えの説明は明確ではありません。
- 最大の潜在的な問題は、
ORDER BY
句を使用してデータベースで明示的な並べ替えを指定していないことです。コストが高すぎると思われるためではない場合、プログラムにバグがあります。データベースは、結果を指定しない場合、任意の順序で結果を返すことができます。クエリを数回実行し、そのように見えるからといって、偶然データを順番に返すことに依存することはできません。ディスク上で行が再配置されるか、一部が削除されて新しい行が代わりになるか、インデックスが追加されるため、順序が変わる場合があります。何らかの種類の句を指定する必要がありますORDER BY
。速度は正確さなしでは価値がありません。
- また、挿入順序が重要であることの意味も明確ではありません。あなたはデータベース自体の話をしている場合は、あなたがしなければならない実際にこれを追跡する欄があり、それがなければなりません、あなたの中に含まれる
ORDER BY
句。そうでなければ、バグがあります。そのような列がまだ存在しない場合は、追加する必要があります。このような列の一般的なオプションは、挿入タイムスタンプ列または自動インクリメントキーです。自動インクリメントキーはより信頼性があります。
問題2:メモリ内ソートを効率的にする
期待どおりの順序でデータを返すことが保証されていることを確認したら、この事実を活用して、メモリ内のソートをより効率的にすることができます。クエリの結果セットにrow_number()
またはdense_rank()
列(またはデータベースの同等のもの)を追加するだけです。これで、各行にはインデックスがあり、順序がどのようになるかを直接示すことができます。これをメモリ内で簡単にソートできます。インデックスに意味のある名前(などsortedBySomethingIndex
)を付けてください。
ビオラ。これで、データベースの結果セットの順序に依存する必要がなくなりました。
問題3:この処理をコードで行う必要さえありますか?
SQLは実際には非常に強力です。これは、データに対して多くの変換と集約を行うことができる驚くべき宣言型言語です。ほとんどのDBは、今日では行間操作もサポートしています。それらは、ウィンドウ関数または分析関数と呼ばれます。
このようにデータをメモリに取り込む必要さえありますか?または、ウィンドウ関数を使用して、SQLクエリですべての作業を実行できますか?DBでの作業のすべて(または多分かなりの部分)を行うことができれば、素晴らしいです!コードの問題はなくなります(または、もっと簡単になります)!
問題4:あなたはそれに対して何をしているのdata
ですか?
DBですべてを行うことはできないと仮定して、これをまっすぐにさせてください。データをマップとして取得し(並べ替えたくないものによってキー設定されます)、挿入順にデータを反復処理し、いくつかのキーの値を置き換えて追加してマップをその場で変更します新しいもの?
申し訳ありませんが、一体何ですか?
呼び出し元は、これらすべてを心配する必要はありません。作成したシステムは非常に脆弱です。ちょっとした間違った変更を行うのに、たった1つの愚かな間違い(たぶん自分で行ったのかもしれません)があれば、すべてがカードのデッキのように崩壊します。
ここにもっと良いアイデアがあります:
- 関数でを受け入れます
List
。
- 注文の問題に対処するには、いくつかの方法があります。
- フェイルファーストを適用します。リストが関数に必要な順序になっていない場合、エラーをスローします。(注:問題2のソートインデックスを使用して、ソートインデックスがあるかどうかを確認できます。)
- ソートされたコピーを自分で作成します(再び問題2のインデックスを使用します)。
- マップ自体を順番に構築する方法を見つけてください。
- 関数の内部で必要なマップを作成して、呼び出し元が気にする必要がないようにします。
- 今、あなたが持っている順序表現で何でも繰り返し、あなたがしなければならないことをします。
- マップを返すか、適切な戻り値に変換します
可能性のあるバリエーションは、ソートされた表現を構築し、インデックスのキーのマップを作成することです。これにより、誤って複製を作成することなく、ソートされたコピーを適切に変更できます。
または、これはもっと理にかなっているかもしれません:data
パラメータを取り除き、processData
実際に独自のデータをフェッチします。データを取得する方法に関して非常に特定の要件があるため、これを実行していることを文書化できます。言い換えれば、関数がプロセスの一部ではなく、プロセス全体を所有するようにします。相互依存関係が強すぎて、ロジックを小さなチャンクに分割できません。(プロセス内の関数の名前を変更します。)
たぶん、これらはあなたの状況では機能しません。私は問題の完全な詳細なしで知りません。しかし、私が聞いたとき、私は壊れやすく紛らわしいデザインを知っています。
概要
ここでの問題は、最終的に悪魔が細部にあることだと思います。このような問題が発生し始めたのは、通常、実際に解決しようとしている問題に対するデータの不適切な表現があるためです。最良の解決策は、より適切な表現を見つけることであり、その後、私の問題は簡単に(おそらく簡単ではないが、簡単に)解決できます。
そのポイントを得る誰かを見つけてください:あなたの仕事は、あなたの問題を単純で簡単な問題のセットに減らすことです。その後、堅牢で直感的なコードを構築できます。彼らと話してください。優れたコードと優れたデザインは、単純で簡単なため、どんな馬鹿でも考え抜かれたと思わせるでしょう。たぶんあなたが話すことができるそのような考え方を持っている上級開発者がいるでしょう。