2

Amazon SimpleDB に保存したデータを中継するサーバーにクエリを実行する iPhone アプリを開発しています。さまざまなユーザーによる「提出」のデータベーステーブルがあります。私は Facebook とインターフェースして Facebook の友達を取得しており、「Submissions」にクエリを作成して、友​​達の投稿を見つけたいと考えています。

SELECT * FROM submissions WHERE userID = '00123' OR userID = '00124' OR .... 

(友達の完全なリストを介して)

これは、この種の選択ステートメントでAmazonクエリの制限に達すると思います-

[Select 式あたりの最大比較数: 20]

SimpleDB でこれをエレガントに実現する方法を考えられますか? 20 人のクエリを大量に実行する必要はありません。または、別のデータベース パッケージに移動してクロステーブル クエリを実行する必要がありますか?

ありがとう!

4

3 に答える 3

4

SimpleDB でそれを行う方法はありますが、洗練されたものではありません。送信アイテムで userid 属性を人為的に複製する必要があるため、ハックのようなものです。

これは、IN 述語ごとに 20 の比較しかできないが、それぞれが異なる属性を指定する場合、 20 の IN 述語を持つことができるという事実に基づいています。したがって、フォームの送信項目に追加の合成属性を追加します。

userID='00123' userID_2='00123' userID_3='00123' userID_4='00123' ... userID_20='00123'

それらはすべて、特定の提出に対して同じ値を持ちます。次に、1 つのクエリで最大 400 人の友達の投稿を取得できます。

SELECT * FROM submissions 
WHERE userID IN('00120','00121',...,'00139') OR
    `userID_2` IN('00140','00141',...,'00159') OR
    `userID_3` IN('00160','00161',...,'00179') OR
    `userID_4` IN('00180','00181',...,'00199') OR
    ...
    `userID_20` IN('00300','00301',...,'00319')

申請の作成時に 19 個の追加の属性を設定でき (属性に余裕がある場合)、申請のユーザーが変更されることはないようです。また、返される属性に ( * を使用する代わりに) 明示的に名前を付けることもできます。これは、返されるデータ セットで気にしない属性が 19 個あるためです。

データ モデルの観点からは、これは明らかにハックです。しかし、そうは言っても、友達が 400 人以下のユーザーの場合、まさにあなたが望むものを提供します: 1 つのクエリで、日付やその他の基準で制限したり、最近のもので並べ替えたり、結果をページスルーしたりできます。残念ながら、容量of 400 では、すべての Facebook ユーザーの友達リストに対応することはできません。そのため、大規模なフレンド リストに対しても、同じようにマルチクエリ ソリューションを実装する必要がある場合があります。

この問題を除いて、SimpleDB がアプリのニーズに合っている場合は、ハックの使用を検討してください。しかし、このようなことを繰り返し行う必要がある場合、SimpleDB はおそらく最良の選択ではありません。

于 2010-08-06T15:15:45.883 に答える
2

IN 句または一時テーブルへの結合が必要です。残念ながら、AmazonSimpleDB には制限があります。まさにこの理由で、有望なプロジェクトでそれを放棄しました。ギアを切り替える前に、マルチスレッド化と NextToken 機能の使用の道をたどりました。

SimpleDB に対して並列 (マルチスレッド) クエリを実行して送信を取得できます。各クエリは最大 20 のユーザー ID を検索し、結果を 1 つのリストにマージします。それでも、ID のリストを一時テーブルとしてアップロードし、単純な結合を実行して結果を取得できるようにするために、MySQL または SQL Server への切り替えを検討する時期が来ていると思われます。

于 2010-08-06T01:34:13.600 に答える
1

私は SimpleDB 用の Simple Savant .NET ライブラリを作成しました。各 select の IN 句を 20 個の値に制限しながら、分割して複数の select クエリを並行して実行するためのユーティリティ コードがいくつかあります。私はおそらくこのコードを次の Savant リリースにロールバックしますが、これが役に立つと思う人のためにここにあります:

    /// <summary>
    /// Invokes select queries that use parameter lists (with IN clauses) by splitting the parameter list
    /// across multiple invocations that are invoked in parallel.
    /// </summary>
    /// <typeparam name="T">The item type</typeparam>
    /// <typeparam name="P">The select parameter type</typeparam>
    /// <param name="savant">The savant instance.</param>
    /// <param name="command">The command.</param>
    /// <param name="paramValues">The param values.</param>
    /// <param name="paramName">Name of the param.</param>
    /// <returns></returns>
    public static List<T> SelectWithList<T,P>(ISimpleSavantU savant, SelectCommand<T> command, List<P> paramValues, string paramName)
    {
        var allValues = SelectAttributesWithList(savant, command, paramValues, paramName);
        var typedValues = new List<T>();
        foreach (var values in allValues)
        {
            typedValues.Add((T)PropertyValues.CreateItem(typeof (T), values));
        }
        return typedValues;
    }

    /// <summary>
    /// Invokes select queries that use parameter lists (with IN clauses) by splitting the parameter list
    /// across multiple invocations that are invoked in parallel.
    /// </summary>
    /// <typeparam name="P">The select parameter type</typeparam>
    /// <param name="savant">The savant instance.</param>
    /// <param name="command">The command.</param>
    /// <param name="paramValues">The param values.</param>
    /// <param name="paramName">Name of the param.</param>
    /// <returns></returns>
    public static List<PropertyValues> SelectAttributesWithList<P>(ISimpleSavantU savant, SelectCommand command, List<P> paramValues, string paramName)
    {
        Arg.CheckNull("savant", savant);
        Arg.CheckNull("command", command);
        Arg.CheckNull("paramValues", paramValues);
        Arg.CheckNullOrEmpty("paramName", paramName);

        var allValues = new List<PropertyValues>();
        if (paramValues.Count == 0)
        {
            return allValues;
        }

        var results = new List<IAsyncResult>();
        do
        {
            var currentParams = paramValues.Skip(results.Count * MaxValueTestsPerSimpleDbQuery).Take(MaxValueTestsPerSimpleDbQuery).ToList();
            if (!currentParams.Any())
            {
                break;
            }
            var currentCommand = Clone(command);
            currentCommand.Reset();
            var parameter = currentCommand.GetParameter(paramName);
            parameter.Values.Clear();
            parameter.Values.AddRange(currentParams.Select(e => (object)e));
            var result = savant.BeginSelectAttributes(currentCommand, null, null);
            results.Add(result);
        } while (true);

        foreach (var result in results)
        {
            var values = ((ISimpleSavant2)savant).EndSelectAttributes(result);
            allValues.AddRange(values);
        }

        return allValues;
    }

    private static SelectCommand Clone(SelectCommand command)
    {
        var newParameters = new List<CommandParameter>();
        foreach (var parameter in command.Parameters)
        {
            var newParameter = new CommandParameter(parameter.Name, parameter.PropertyName, null);
            newParameter.Values.Clear();
            newParameters.Add(newParameter);
        }
        var newCommand = new SelectCommand(command.Mapping, command.CommandText, newParameters.ToArray())
            {
                MaxResultPages = command.MaxResultPages
            };
        return newCommand;
    }
于 2010-09-16T01:42:54.553 に答える