【发布时间】:2015-03-09 16:28:46
【问题描述】:
简单的网络应用,托管在使用 PHP 和 MySql 后端的标准共享主机上。
我有两个相对较小的表(每个表几百行),当我使用连接查询时,查询可能需要两到三秒。
这是一张桌子:'students':
CREATE TABLE IF NOT EXISTS `students` (
`_id` mediumint(9) NOT NULL AUTO_INCREMENT,
`firstname` char(30) NOT NULL,
`lastname` char(30) NOT NULL,
`dateOfBirth` date DEFAULT NULL,
`gender` varchar(10) NOT NULL,
`knownasname` varchar(30) NOT NULL,
`school` varchar(30) DEFAULT NULL,
`schoolyear` varchar(30) DEFAULT NULL,
`notes` text,
`foundusvia` varchar(30) DEFAULT NULL,
`dateadded` datetime NOT NULL,
`archived` tinyint(1) DEFAULT NULL,
PRIMARY KEY (`_id`),
UNIQUE KEY `_id` (`_id`)
) ENGINE=InnoDB DEFAULT CHARSET=latin1 AUTO_INCREMENT=684 ;
这是第二个:
CREATE TABLE IF NOT EXISTS `contacts` (
`_id` mediumint(9) NOT NULL AUTO_INCREMENT,
`student_id` mediumint(9) NOT NULL,
`studentAddressStreet` varchar(50) DEFAULT NULL,
`studentAddressArea` varchar(30) DEFAULT NULL,
`studentAddressTown` varchar(30) DEFAULT NULL,
`studentAddressPostcode` varchar(30) DEFAULT NULL,
`studentPhoneMobile` varchar(30) DEFAULT NULL,
`studentPhoneLand` varchar(30) DEFAULT NULL,
`studentAddressNotes` text,
`studentemail` varchar(50) DEFAULT NULL,
`billingAddressStreet` varchar(50) DEFAULT NULL,
`billingAddressArea` varchar(30) DEFAULT NULL,
`billingAddressTown` varchar(30) DEFAULT NULL,
`billingAddressPostcode` varchar(30) DEFAULT NULL,
`billingPhoneMobile` varchar(30) DEFAULT NULL,
`billingPhoneLand` varchar(30) DEFAULT NULL,
`billingContactName` varchar(30) DEFAULT NULL,
`billingContactRelationship` varchar(30) DEFAULT NULL,
`billingAddressNotes` text,
`billingemail` varchar(50) DEFAULT NULL,
`caregiverAddressStreet` varchar(50) DEFAULT NULL,
`caregiverAddressArea` varchar(30) DEFAULT NULL,
`caregiverAddressTown` varchar(30) DEFAULT NULL,
`caregiverAddressPostcode` varchar(30) DEFAULT NULL,
`caregiverPhoneMobile` varchar(30) DEFAULT NULL,
`caregiverPhoneLand` varchar(30) DEFAULT NULL,
`caregiverContactName` varchar(30) DEFAULT NULL,
`caregiverContactRelationship` varchar(30) DEFAULT NULL,
`caregiverAddressNotes` text,
`caregiveremail` varchar(50) DEFAULT NULL,
PRIMARY KEY (`_id`),
KEY `contacts_index` (`student_id`)
) ENGINE=InnoDB DEFAULT CHARSET=latin1 AUTO_INCREMENT=290 ;
这是查询:
它的工作是从表“students”和“contacts”中为具有给定_id的学生获取所有数据。
SELECT *
FROM students, contacts
WHERE students._id = contacts.student_id
AND students._id =99 <=== This value obviously changes
表contacts 在student_id 上有一个索引
学生表有一个关于名字和姓氏的索引。
让这个查询需要 2 到 3 秒才能运行有什么问题?表很小,查询很简单。非常感谢任何帮助!
编辑:这是 EXPLAIN 的输出。还修改了联系人表的 CREATE
id | select_type | table | type | possible_keys | key | key_len | ref | rows | Extra
===|=============|=========|======|===============|==============|=========|======|=============
1 | SIMPLE | students|const | PRIMARY | PRIMARY | 3 |const | 1 |
1 | SIMPLE | contacts|ref | contacts_index|contacts_index| 3 |const | 1 |
【问题讨论】:
-
在
contacts表中在(student_id)上创建索引。 -
另外加上
EXPLAIN。顺便说一句UNIQUE KEY_id` (_id)` 是多余的 -
只选择你想要的列。使用正确的 JOIN 语法加入。并在contacts.student_id上放置一个索引
-
@zerkms 我怀疑这些东西是由应用程序生成的。
-
您说“表
contacts在 student_id 上有一个索引”,但它没有显示在您的CREATE TABLE语句中。
标签: mysql select optimization