0

特定のエンティティのステータス/メッセージ更新のページを作成しようとしています。ユーザーは任意の数のエンティティをサブスクライブでき、このページで最新の情報を取得できます。私の現在のクエリは、実行に時間がかかります (1.3+ 秒、200K 行のテスト テーブルで)。これは、50 行程度を取得するだけです。

スキーマは次のとおりです。

実在物:

  entity_id, message, timestamp

ユーザー

  user_id

サブスクリプション

  user_id, entity_id

クエリは次のとおりです。

   SELECT entity.*
   FROM entity
   INNER JOIN subscription ON subscription.entity_id = entity.entity_id
   WHERE subscription.user_id = 1
   ORDER BY entity.timetamp DESC 
   LIMIT 50

データベース側の問題は次のようです。

   Copying to tmp table 0.033285
   converting HEAP to MyISAM    0.031850
   Copying to tmp table on disk 1.177973
   Sorting result   0.064075

サブスクリプション テーブルで、次の説明情報を取得します。一時的な使用; ファイルソートの使用

InnoDB テーブルを使用しており、entity_id、user_id、および timestamp 列にインデックスがあります

更新: order by が原因であるか、問題であると思われます。タイムスタンプ列にインデックスがあるので、それ以外に、最新のメッセージをより迅速に取得するために他に何ができますか?

更新: order by 句を削除すると、クエリがすばやく実行されます。0.0006 秒対 1.3。そのため、最初にサブクエリを介してデータを取得してから order by を実行しようとしましたが、これは何もしません。

使用したクエリは次のとおりです。

SELECT tbl.* FROM ( 
   SELECT entity.*
   FROM entity
   INNER JOIN subscription ON subscription.entity_id = entity.entity_id
   WHERE subscription.user_id = 1
) as tbl
ORDER BY tbl.timetamp DESC 
4

3 に答える 3

0

エンティティ テーブルでは、 entity_id と timestamp の両方をこの順序でカバーする単一のインデックスが必要です。これが主キーである場合に最適です。サブスクリプション テーブルでは、 user_id と entity_id の両方をこの順序でカバーするインデックスが必要です。これらのインデックスには、同じインデックスに両方の列が含まれていることが重要です。

それが完了したら、テーブルとインデックスの両方を RAM に完全に保持できる十分な RAM が MySql にあることを確認してから、いくつかのサンプル クエリを実行してデータベース キャッシュを「ウォームアップ」する前に実際のベンチマークを実行します。

また、エンティティ テーブルとは別のメッセージ テーブルが必要になることをお勧めします。これは、実際にここで表示するメッセージ テーブルです。

于 2013-10-04T23:03:24.907 に答える
0

各 EntityID の TOP 50 を意図していないことを確認してください。この場合、クエリは大きく異なります。クエリで LIMIT を使用した方法は、タイムスタンプで並べ替えられた最大 50 行を取得することを意味します。

2 番目が true の場合、大きなテーブルを初めてフィルタリングできます。また、クエリで「Order By」を使用する場合は、WHERE 条件で使用できる定数/リストを考えてみてください。そうすれば、DB エンジンはインデックスをより効率的に利用できます。

必要なインデックス。

テーブル エンティティ:

TimeStamp DESC, EntityID ASC, Message ASC

テーブル サブスクリプション:

User_id,entity_ID

このクエリを試す

    SET @Rownum=1
    SET @PValue=''

    SELECT Entity_ID,Message,TIMESTAMP
    FROM
    (
        SELECT
            @Rownum:=IF(@Timestamp=Timestamp, @Rownum+1,1) AS RowNumber
            ,Entity_ID
            ,MESSAGE
            ,TimeStamp
            @Timestamp=@Timestamp AS DummyTimeStamp
        FROM Enitty
        WHERE Entity_ID IN (SELECT Entity_ID FROM Subscription WHERE USER_ID = 1)
        ORDER BY Timestamp DESC
    )qry
    WHERE RowNumber <=50
于 2013-10-05T03:03:45.847 に答える