简单的网络应用程序,使用 PHP 和 MySql 后端托管在标准共享托管上。
我有两个相对较小的表(每个表只有几百行),当我使用联接进行查询时,查询可能需要两到三秒的时间。
这是一张表:“学生”:
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 |
最佳答案
专业提示:如果可能,请避免 SELECT *
。这在 JOIN 上尤其成问题。
如果您使用标准 JOIN,就像这样,您将可以更轻松地阅读查询。以逗号分隔的表列表 jumped the shark 20 世纪 90 年代末的某个时候。
SELECT students.*,
contacts.*
FROM students
LEFT JOIN contacts ON students._id = contacts.student_id
WHERE students._id =99
最后,在 contacts
表的 student_id
列上放置一个索引,以便联接可以快速访问该表。
关于mysql - 表和查询优化,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/28933527/