假设,我有一个正常的规范化数据库,如下所示:

CREATE TABLE `users` (
  `id` int(10) unsigned NOT NULL AUTO_INCREMENT,
  `name` varchar(80) NOT NULL,
  PRIMARY KEY (`id`)
) ENGINE=InnoDB  DEFAULT CHARSET=latin1 AUTO_INCREMENT=3 ;
INSERT INTO `users` (`id`, `name`) VALUES
(1, 'test'),
(2, 'user');

_
CREATE TABLE `groups` (
  `id` int(10) unsigned NOT NULL AUTO_INCREMENT,
  `name` varchar(80) NOT NULL,
  PRIMARY KEY (`id`)
) ENGINE=InnoDB  DEFAULT CHARSET=latin1 AUTO_INCREMENT=2 ;
INSERT INTO `groups` (`id`, `name`) VALUES
(1, 'test');

_
CREATE TABLE `Data` (
  `id` int(10) unsigned NOT NULL AUTO_INCREMENT,
  `user` int(10) unsigned NOT NULL,
  `group` int(10) unsigned NOT NULL,
  `time` int(10) unsigned NOT NULL,
  `data` varchar(100) COLLATE utf8_unicode_ci NOT NULL,
  PRIMARY KEY (`id`),
  KEY `user` (`user`),
  KEY `group` (`group`)
) ENGINE=InnoDB  DEFAULT CHARSET=utf8 COLLATE=utf8_unicode_ci AUTO_INCREMENT=3 ;

INSERT INTO `Data` (`id`, `user`, `group`, `time`, `data`) VALUES
(1, 2, 1, 1301861998, 'something'),
(2, 1, 1, 1301862045, 'something else');

ALTER TABLE `Data`
  ADD CONSTRAINT `Data_ibfk_2` FOREIGN KEY (`group`) REFERENCES `groups` (`id`) ON DELETE CASCADE ON UPDATE CASCADE,
  ADD CONSTRAINT `Data_ibfk_1` FOREIGN KEY (`user`) REFERENCES `users` (`id`) ON DELETE CASCADE ON UPDATE CASCADE;

现在我要创建一个视图,它显示了这个数据库的非规范化,以便于手动浏览。
如何正确创建此视图?
到目前为止我得到的是:
CREATE VIEW `data_view` AS
  select `Data`.`id`,
 (select `users`.`name` AS `name` from `users` where (`users`.`id` = `Data`.`user`)) AS `user`,
 (select `groups`.`name` AS `name` from `groups` where (`groups`.`id` = `Data`.`group`)) AS `group`,
 from_unixtime(`Data`.`time`) AS `time`,
 `Data`.`data` AS `data` from `Data`;

它可以工作,但是由于有两个内部SELECT语句,它的速度非常慢。(对于一个大约有200万行的数据库,对于数据表上的同一个查询,它需要一分钟以上而不是少于一秒钟。
我的猜测是,获取用户和组友好名称的select语句是针对每一行执行的,而不是缓存的。
我如何优化这个?

最佳答案

CREATE VIEW `data_view` AS
  select `Data`.`id`,
  `users`.`name` as `user`,
  `groups`.`name` as `group`,
 from_unixtime(`Data`.`time`) AS `time`,
 `Data`.`data` AS `data` from `Data`
 INNER JOIN `users` ON (`users`.`id` = `Data`.`user`)
 INNER JOIN `groups` where (`groups`.`id` = `Data`.`group`)

试试这个。并确保users.id、groups.id、data.user和data.group是索引。。
mysql中的内部选择比连接慢得多。

10-07 19:42
查看更多