SELECT test2.*, account.*
FROM test2
JOIN account on test2.account_id = account.id
where test2.id > 0
and test2.active = TRUE
and account.age BETWEEN 18 AND 80 AND account.gender = 'MALE'
ORDER BY test2.id DESC
LIMIT 20
CREATE TABLE `account` (
`id` int(11) NOT NULL AUTO_INCREMENT,
`email` varchar(45) NOT NULL,
`username` varchar(30) NOT NULL,
`password` varchar(100) NOT NULL,
`location_id` int(11) NOT NULL DEFAULT '0',
`country` varchar(40) DEFAULT NULL,
`gender` varchar(11) NOT NULL,
`role` varchar(10) NOT NULL DEFAULT 'USER',
`bio` varchar(255) CHARACTER SET utf8mb4 COLLATE utf8mb4_0900_ai_ci DEFAULT NULL,
`main_profile_pic_uuid` char(32) CHARACTER SET ascii COLLATE ascii_general_ci DEFAULT NULL,
`picture_verified` tinyint(1) NOT NULL DEFAULT '0',
`looking_for` varchar(20) DEFAULT NULL,
`include_in_search` tinyint(1) NOT NULL DEFAULT '1',
`age` tinyint(4) NOT NULL,
`latitude` double DEFAULT '0',
`longitude` double DEFAULT '0',
`updated` timestamp NOT NULL DEFAULT CURRENT_TIMESTAMP,
`last_active` timestamp NOT NULL DEFAULT CURRENT_TIMESTAMP,
`created` timestamp NOT NULL DEFAULT CURRENT_TIMESTAMP,
PRIMARY KEY (`id`),
UNIQUE KEY `account_username_uindex` (`username`),
KEY `account_email_index` (`email`),
KEY `account_location_id_fk` (`location_id`),
KEY `account_multi_index` (`include_in_search`,`location_id`,`gender`,`looking_for`,`age`,`picture_verified`),
KEY `account_multi2_index` (`include_in_search`,`looking_for`,`age`,`location_id`,`gender`,`picture_verified`),
KEY `account_multi3_index` (`include_in_search`,`looking_for`,`age`,`gender`,`picture_verified`,`location_id`),
KEY `account_available_for_chat_index` (`available_for_chat`),
CONSTRAINT `account_location_id_fk` FOREIGN KEY (`location_id`) REFERENCES `location` (`id`)
) ENGINE=InnoDB AUTO_INCREMENT=710538 DEFAULT CHARSET=utf8mb4 COLLATE=utf8mb4_0900_ai_ci
CREATE TABLE `test2` (
`id` int(11) NOT NULL AUTO_INCREMENT,
`account_id` int(11) NOT NULL,
`duration` smallint(6) NOT NULL DEFAULT '30',
`began` timestamp NOT NULL DEFAULT CURRENT_TIMESTAMP,
`ending` timestamp NOT NULL DEFAULT '0000-00-00 00:00:00',
`active` tinyint(1) NOT NULL DEFAULT '1',
`latitude` double NOT NULL,
`longitude` double NOT NULL,
PRIMARY KEY (`id`),
KEY `test2_active_ending_index` (`active`,`ending`),
KEY `test2_account_id_fk` (`account_id`,`id` DESC),
CONSTRAINT `test2_account_id_fk` FOREIGN KEY (`account_id`) REFERENCES `account` (`id`) ON DELETE CASCADE
) ENGINE=InnoDB AUTO_INCREMENT=1002031 DEFAULT CHARSET=utf8mb4 COLLATE=utf8mb4_0900_ai_ci
Кстати, test2 имеет около 1 миллиона строк ПОСЛЕ фильтрации, учетная запись имеет около 700k также после фильтрации.
Выше работает примерно в 2se c с filesort
, слишком медленно:
1 SIMPLE account ALL PRIMARY 702300 1.11 Using where; Using temporary; Using filesort
1 SIMPLE test2 ref PRIMARY,test2_active_ending_index,test2_account_id_fk test2_account_id_fk 4 db.account.id 2 25 Using index condition; Using where
Если я достану бит "and account.age МЕЖДУ 18 И 80 И account.gender = 'MALE'", НО оставлю "ЗАКАЗАТЬ BY test2.id DES C ", работает за 10 мсек, нет filesort
.
Если я достану " ORDER BY test2.id DES C " бит, НО сохранять " "и account.age между 18 и 80 AND account.gender = 'MALE'" , работает в 10 мс, нет filesort
. Нет заказа по:
1 SIMPLE account ALL PRIMARY 702300 1.11 Using where
1 SIMPLE test2 ref PRIMARY,test2_active_ending_index,test2_account_id_fk test2_account_id_fk 4 db.account.id 2 25 Using index condition; Using where
Все поля имеют индивидуальные или составные индексы.
Кто-нибудь знает, как сократить время выполнения или избавиться от filesort
?
У меня есть еще одна не связанная с этим таблица, по дизайну она очень похожа на test2, с 1 милом строк, и когда я выполняю точно такой же запрос, она выполняется очень быстро:
1 SIMPLE new_table range PRIMARY,new_table_account_id_fk PRIMARY 4 498496 100 Using where; Backward index scan
1 SIMPLE account eq_ref PRIMARY PRIMARY 4 db.new_table.account_id 1 5 Using where
Обратите внимание на разница по типу & ref & extra, по сравнению с test2. Я попытался ограничить количество строк аккаунта для test2 до 300k, при той же скорости и результате.