0

ちょっとした入門書です。私は PHP/JS/C 開発のエキスパートですが、MySQL を包括的に把握できたことはありません。私の質問に答えていただけると助かりますが、(主に効率の観点から) 複雑な MySQL クエリの推奨事項と禁止事項について学ぶための優れたリソースの方向性を教えていただけると助かります。

目的

結果セット全体を取得しながら、単一のテーブルで類似点/重複を見つける必要があります (別のテーブルにある実際のタイトル/説明のコンテンツと LEFT JOIN するため)。

表は非常に単純です。3 つの列 ( pageusertime) が含まれます。

基本的に、各クエリには 2 人のユーザーがいます。User 1一致するすべての結果の数、一致するすべての結果の数User 2、およびオーバーラップのすべての列 (および LEFT JOIN)をプルする必要があります (テーブル内でUser 1との両方が一致する場合)。User 2

サンプルクエリ

このクエリは機能しますが、非常に遅く (実行に数分かかるところまで)、サブクエリのために非効率的であると推測しています。SQL の専門家がこれを行うためのより効率的な方法 (およびその理由) を指摘できる場合は、大いに感謝します。

SELECT DISTINCT `page`, 
    (SELECT COUNT(*) FROM `m_likes` WHERE `user` = "1") AS userLikes,
    (SELECT COUNT(*) FROM `m_likes` WHERE `user` = "2") AS friendLikes

    FROM `m_likes` LEFT JOIN `app_pages` AS page ON (page.id = `page`)

        WHERE `page` IN (SELECT `page` FROM `m_likes` WHERE `user` = "1") 
        AND `page` IN (SELECT `page` FROM `m_likes` WHERE `user` = "2")

        AND (`user` = "1" OR `user` = "2")

EXPLAIN クエリ結果

id  select_type table   type    possible_keys   key key_len ref rows    Extra
1   PRIMARY     m_likes index   NULL    page    604 NULL    35043   Using where; Using index; Using temporary
1   PRIMARY     page    eq_ref  PRIMARY PRIMARY 767 tablename.m_likes.page  1   
5   DEPENDENT SUBQUERY  m_likes unique_subquery page    page    604 func,const      1   Using index; Using where
4   DEPENDENT SUBQUERY  m_likes unique_subquery page    page    604 func,const      1   Using index; Using where
3   SUBQUERY    m_likes index   NULL    page    604 NULL    35043   Using where; Using index
2   SUBQUERY    m_likes index   NULL    page    604 NULL    35043   Using where; Using index

テーブル スキーマ

app_pages : idVARCHAR(255)、nameVARCHAR(255)、categoryVARCHAR(255)

m_likes : pageVARCHAR(255)、userVARCHAR(255)、timeINT(20)

m_likes.page = app_pages.id

残念ながら、ユーザー ID とページ ID は INT ではなく VARCHAR である必要があります。これは、64 ビット システムで実行される保証がなく、一部の ID 値が 32 ビット システムで許可されている最大値よりも大きいためです。システム...うまくいけば、パフォーマンスに大きな影響を与えません。

出力例

array (size=156)
  0 => 
    array (size=6)
      'page' => string '100861973286778' (length=15)
      'time' => string '1297383617' (length=10)
      'name' => string 'Leila' (length=5)
      'category' => string 'Book' (length=4)
      'userLikes' => string '104' (length=3)
      'friendLikes' => string '52' (length=2)
  1 => 
    array (size=6)
      'page' => string '10150160788195604' (length=17)
      'time' => string '1272653871' (length=10)
      'name' => string 'Frisbee Golfing' (length=15)
      'category' => string 'Interest' (length=8)
      'userLikes' => string '104' (length=3)
      'friendLikes' => string '52' (length=2)
4

1 に答える 1

1

クエリの実行が非常に遅い理由は、実際には各行に対して実行される 4 つの個別のサブクエリを実行しているためです。

代わりに、副選択のデカルト積を実行して合計カウントを取得できます (1 回のみ実行されます)。

SELECT a.page, c.userLikes, c.friendLikes
FROM m_likes a
INNER JOIN app_pages b ON a.page = b.id
CROSS JOIN
(
    SELECT
        COUNT(CASE WHEN user = '1' THEN 1 END) AS userLikes,
        COUNT(CASE WHEN user = '2' THEN 1 END) AS friendLikes
    FROM m_likes
    WHERE user IN ('1','2')
) c
WHERE a.user IN ('1','2')
GROUP BY a.page
HAVING COUNT(1) = 2

このクエリは、ユーザー 1 と 2 の両方がいいね! したすべてのページと、いいね! の合計数 (結果セットで繰り返されます) を取得します。

于 2012-07-23T00:14:56.950 に答える