0

次のようなテーブルがあります。

ID | objectID | time | ...
-------------------
 1 |        1 | ...
 2 |        1 | ...
 3 |        1 | ...
 4 |        2 | ...
 5 |        2 | ...
 6 |        3 | ...
 7 |        4 | ...

ID は主キーであり、objectID は一意ではありません。すべてのオブジェクト ID の最新のエントリを取得するためにクエリのパフォーマンスを向上させようとしていますが、エントリは特定の値よりも新しいものであってはなりません。私は次の 2 つのクエリを試してみましたが、どちらも同じ (そして正しい結果) を提供するはずです。

SELECT *
FROM (
    SELECT *
    FROM table
    WHERE time <= XXX
    ORDER BY time DESC
)
GROUP BY objectID

SELECT *
FROM table AS t     
INNER JOIN (
    SELECT ID, MAX(time)
    FROM table
    WHERE time <= 1353143351
    GROUP BY objectID
) s
USING (ID)

最初のクエリの EXPLAIN が教えてくれます

id | select_type | table      | type | possible_keys | key     | key_len | ref  | rows   | Extra
------------------------------------------------------------------------------------
1  | PRIMARY     | <derived2> | ALL  | NULL          | NULL    | NULL    | NULL | 145827 | Using temporary; Using filesort
2  | DERIVED     | tbl_test   | ALL  | NULL          | NULL    | NULL    | NULL | 238694 | Using filesort

2番目のクエリについては、

id | select_type | table      | type   | possible_keys | key     | key_len | ref  | rows   | Extra
------------------------------------------------------------------------------------
1  | PRIMARY     | <derived2> | ALL    | NULL          | NULL    | NULL    | NULL | 325 
1  | PRIMARY     | t          | eq_ref | PRIMARY,ID    | PRIMARY | 4       | s.ID | 1   
2  | DERIVED     | tbl_test   | index  | NULL          | ID      | 12      | NULL | 238694 | Using where; Using index; Using temporary; Using filesort

(tbl_test はテスト用のテーブルです)

2 番目のクエリは (はるかに) 高速であるように見えますが、実行時間は ~200k DB エントリで 0.1 秒と極端に高速ではありません。クエリのパフォーマンスを向上させる方法はありますか? 不足しているインデックスはありますか?

前もって感謝します!!

編集:eggysクエリの説明(彼の投稿のクエリを参照):

id  select_type table   type    possible_keys   key key_len ref rows    Extra
1   PRIMARY <derived2>  ALL NULL    NULL    NULL    NULL    325 
1   PRIMARY lab_case_test   ALL NULL    NULL    NULL    NULL    238694  Using where; Using join buffer
2   DERIVED lab_case_test   index   NULL    ID  12  NULL    238694  Using where; Using index; Using temporary; Using f...

CREATE TABLE `lab_case_test` (
 `ID` int(11) NOT NULL AUTO_INCREMENT,
 `caseID` int(11) NOT NULL,
 `time` int(11) NOT NULL,
 // ....
 PRIMARY KEY (`ID`),
 KEY `ID` (`ID`,`caseID`,`time`),
 KEY `caseID` (`caseID`,`time`)
) ENGINE=MyISAM AUTO_INCREMENT=238695 DEFAULT CHARSET=utf8
4

1 に答える 1

1

次の複合インデックスが必要です(objectID, time)

ALTER TABLE my_table ADD INDEX (objectID, time)

timeこれは、MySQL がインデックス ツリーからそれぞれの最大値をobjectID直接取得できるためです。次に、テーブルに対して再度結合する際に同じインデックスを使用して、2 番目のクエリのようなものを使用してグループごとの最大レコードを見つけることもできます (ただし、両方objectIDで結合する必要があります。このような場合timeは a を使用するのNATURAL JOINが好きです)。

SELECT *
FROM   my_table NATURAL JOIN (
  SELECT   objectID, MAX(time) time
  FROM     my_table
  WHERE    time <= 1353143351
  GROUP BY objectID
) t
于 2013-03-28T19:16:55.860 に答える