これが私の2つのクエリです。
select sts_in
from sta_session
where sts_user_id=2006
AND sts_sessid!='0jitkt80gg3avere03tqk4lhi6'
order by sts_in desc limit 1;
そして
select max(sts_in)
from sta_session
where sts_user_id=2006
AND sts_sessid!='0jitkt80gg3avere03tqk4lhi6';
参考までに、表は次のようになります。
CREATE TABLE `sta_session` (
`sta_session_id` bigint(20) unsigned NOT NULL AUTO_INCREMENT,
`sts_sessid` varchar(255) NOT NULL COMMENT 'PHP session ID',
`sts_user_id` int(10) unsigned NOT NULL,
`sts_in` bigint(20) NOT NULL,
`sts_out` bigint(20) NOT NULL,
`sts_ip` varchar(255) NOT NULL,
`sts_browser_id` int(10) unsigned NOT NULL,
PRIMARY KEY (`sta_session_id`),
KEY `sts_sessid` (`sts_sessid`),
KEY `sts_user_id` (`sts_user_id`),
KEY `sts_ip` (`sts_ip`),
KEY `fk_sta_browser_id` (`sts_browser_id`),
KEY `idx_last_login` (`sts_user_id`,`sts_in`)
) ENGINE=InnoDB DEFAULT CHARSET=utf8;
両方のクエリでExplainを実行すると、最初のクエリ(order by付き)は、このクエリのために作成した特別なインデックスidx_last_login
を使用しますが、もう1つはsts_user_id
を使用します。
MAXクエリnotはidx_last_login
を利用できますか?何故なの?
seそのインデックスを強制できるので知っていますが、sts_in
の部分を無視してユーザーIDで検索しているだけだと思います。
EXPLAIN、読みやすいJSON形式。
explain select sts_in from sta_session where sts_user_id=2006 AND sts_sessid!='0jitkt80gg3avere03tqk4lhi6' order by sts_in desc limit 1;
[{
"id": 1,
"select_type": "SIMPLE",
"table": "sta_session",
"type": "ref",
"possible_keys": "sts_sessid,sts_user_id,idx_last_login",
"key": "idx_last_login",
"key_len": "4",
"ref": "const",
"rows": 723106,
"Extra": "Using where"
}
]
explain select max(sts_in) from sta_session where sts_user_id=2006 AND sts_sessid!='0jitkt80gg3avere03tqk4lhi6';
[{
"id": 1,
"select_type": "SIMPLE",
"table": "sta_session",
"type": "ref",
"possible_keys": "sts_sessid,sts_user_id,idx_last_login",
"key": "sts_user_id",
"key_len": "4",
"ref": "const",
"rows": 723107,
"Extra": "Using where"
}
]
それは私には非常に理にかなっています。
MySQL Query Optimizerは、WHERE
、_GROUP BY
_、および_ORDER BY
_句を調べます。
最初のクエリを見てください
_select sts_in
from sta_session
where sts_user_id=2006
AND sts_sessid!='0jitkt80gg3avere03tqk4lhi6'
order by sts_in desc limit 1;
_
_sta_session
_のどのインデックスに、WHERE
、_GROUP BY
_、および_ORDER BY
_句で言及されている列が最も多いですか? _idx_last_login
_
MySQLはどのようにしてMAX値を見つけますか?
sts_user_id
_インデックスの_idx_last_login
_をトラバースsts_in
_ 2006の_sts_user_id
_の最後のインデックスエントリに移動sts_sessid!='0jitkt80gg3avere03tqk4lhi6'
_まで後方にスクロールします2番目のクエリを見てください。
_select max(sts_in)
from sta_session
where sts_user_id=2006
AND sts_sessid!='0jitkt80gg3avere03tqk4lhi6';
_
_sta_session
_のどのインデックスに、WHERE
、_GROUP BY
_、および_ORDER BY
_句で言及されている列が最も多いですか? _idx_last_login
_ではなく、_sts_user_id
_です。
MySQLはどのようにしてMAX値を見つけますか?
sts_user_id
_sts_in
_を集計し、_sts_sessid
_のすべての値を比較します<> _'0jitkt80gg3avere03tqk4lhi6'
__sts_user_id
_と_idx_last_login
_は重複したインデックスであるため(最初の列が同じであるため)、次を実行する必要があります。
_ALTER TABLE sta_session DROP INDEX sts_user_id;
_
_idx_last_login
_が選択され、_sts_in
_を集約する可能性があります。ただし、テーブルを横断するトラバースがまだいくつかあります。
インデックス作成を積極的に行いたい場合は、これを作成してください
_ALTER TABLE sta_session ADD INDEX everything_and_the_kitchen_sink_index
(sts_user_id,sts_in,sts_sessid);
_
すべての列(WHERE
、_ORDER BY
_、MAX()
)がインデックス内にあるため、このインデックスが選択され、テーブルに触れる必要がない場合があります。