【发布时间】:2018-09-18 22:38:57
【问题描述】:
我有一个需要大约 15 秒才能完成的子查询的查询。即使我不加入 2 个表,它也很慢,所以不是连接占用了时间。 jos_payplans_subscription 表有 8200 行,大小为 3.3 MB。
某些用户同时拥有有效和过期的会员资格。我想找到所有用户如何不活跃(状态 = 1603)并且没有其他活跃的会员资格。
查询有效 - 只是很慢。
问题:我能做得更好吗?
谢谢
SELECT c.id, c.name, c.username, c.email, a.plan_id, d.title, a.subscription_date, a.expiration_date
FROM jos_payplans_subscription a
LEFT JOIN jos_users c ON c.id = a.user_id
LEFT JOIN jos_payplans_plan d ON d.plan_id = a.plan_id
WHERE a.status = 1603
AND a.user_id NOT IN (SELECT b.user_id FROM jos_payplans_subscription b WHERE b.status = 1601)
这是 3 个表的创建表
CREATE TABLE `jos_payplans_subscription` (
`subscription_id` int(11) NOT NULL AUTO_INCREMENT,
`order_id` int(11) NOT NULL,
`user_id` int(11) NOT NULL,
`plan_id` int(11) NOT NULL,
`status` int(11) NOT NULL DEFAULT '0',
`total` decimal(15,5) DEFAULT '0.00000',
`subscription_date` datetime DEFAULT '0000-00-00 00:00:00',
`expiration_date` datetime DEFAULT '0000-00-00 00:00:00',
`cancel_date` datetime DEFAULT '0000-00-00 00:00:00',
`checked_out` int(11) DEFAULT '0',
`checked_out_time` datetime DEFAULT '0000-00-00 00:00:00',
`modified_date` datetime DEFAULT '0000-00-00 00:00:00',
`params` text NOT NULL,
PRIMARY KEY (`subscription_id`) USING BTREE
) ENGINE=MyISAM AUTO_INCREMENT=15103 DEFAULT CHARSET=utf8
CREATE TABLE `jos_payplans_plan` (
`plan_id` int(11) NOT NULL AUTO_INCREMENT,
`title` varchar(255) NOT NULL,
`published` tinyint(1) DEFAULT '1',
`visible` tinyint(1) DEFAULT '1',
`ordering` int(11) DEFAULT '0',
`checked_out` int(11) DEFAULT '0',
`checked_out_time` datetime DEFAULT '0000-00-00 00:00:00',
`modified_date` datetime DEFAULT '0000-00-00 00:00:00',
`description` text,
`details` text,
`params` text,
PRIMARY KEY (`plan_id`) USING BTREE
) ENGINE=MyISAM AUTO_INCREMENT=28 DEFAULT CHARSET=utf8
CREATE TABLE `jos_users` (
`id` int(11) NOT NULL AUTO_INCREMENT,
`name` varchar(400) COLLATE utf8mb4_unicode_ci NOT NULL DEFAULT '',
`username` varchar(150) COLLATE utf8mb4_unicode_ci NOT NULL DEFAULT '',
`email` varchar(100) COLLATE utf8mb4_unicode_ci NOT NULL DEFAULT '',
`password` varchar(100) COLLATE utf8mb4_unicode_ci NOT NULL DEFAULT '',
`block` tinyint(4) NOT NULL DEFAULT '0',
`sendEmail` tinyint(4) DEFAULT '0',
`registerDate` datetime NOT NULL DEFAULT '0000-00-00 00:00:00',
`lastvisitDate` datetime NOT NULL DEFAULT '0000-00-00 00:00:00',
`activation` varchar(100) COLLATE utf8mb4_unicode_ci NOT NULL DEFAULT '',
`params` mediumtext COLLATE utf8mb4_unicode_ci NOT NULL,
`lastResetTime` datetime NOT NULL DEFAULT '0000-00-00 00:00:00' COMMENT 'Date of last password reset',
`resetCount` int(11) NOT NULL DEFAULT '0' COMMENT 'Count of password resets since lastResetTime',
`otpKey` varchar(1000) COLLATE utf8mb4_unicode_ci NOT NULL DEFAULT '' COMMENT 'Two factor authentication encrypted keys',
`otep` varchar(1000) COLLATE utf8mb4_unicode_ci NOT NULL DEFAULT '' COMMENT 'One time emergency passwords',
`requireReset` tinyint(4) NOT NULL DEFAULT '0' COMMENT 'Require user to reset password on next login',
PRIMARY KEY (`id`) USING BTREE,
KEY `idx_block` (`block`) USING BTREE,
KEY `username` (`username`) USING BTREE,
KEY `email` (`email`) USING BTREE,
KEY `idx_name` (`name`(100)) USING BTREE
) ENGINE=MyISAM AUTO_INCREMENT=23158 DEFAULT CHARSET=utf8mb4 COLLATE=utf8mb4_unicode_ci
【问题讨论】:
-
您是否在搜索使用的字段上添加了索引?你也是在本地还是在网络服务器上进行测试?
-
在询问有关查询优化的问题时,您应该为查询中的每个表运行
SHOW CREATE TABLE <tablename>,并在问题中包含定义。否则,我们必须猜测您的数据类型和索引。还为您询问的 SQL 查询运行EXPLAIN <query>。 -
@BillKarwin 我为 3 个表添加了 show create table。我看到了主表; jos_payplans_subscription 没有索引。
-
@zeflex 我正在一个只运行这个网站的实时高性能网络服务器上进行测试
-
@zeflex 我手动向表中添加了一个新索引,这真的很神奇。从 15 秒到 0.5 秒 - 太棒了 :-) 感谢您的指点 - 没想到,因为该表是作为 Joomla CMS 扩展的一部分而创建的