免费注册 查看新帖 |

Chinaunix

  平台 论坛 博客 文库
1234
最近访问板块 发新帖
楼主: meizhe1981
打印 上一主题 下一主题

虚心求教,mysql 查询优化方案,难道无解? [复制链接]

论坛徽章:
0
31 [报告]
发表于 2008-12-03 10:23 |只看该作者
原帖由 sunnyfun 于 2008-12-3 10:18 发表
其实搞来搞去是楼主的数据模型设计的有问题,完全可以独立建个好友关系表,将in用表连接替换掉,简单的多对多罢了。



这个才是正解。

论坛徽章:
0
32 [报告]
发表于 2008-12-03 11:00 |只看该作者

回复 #30 sunnyfun 的帖子

原帖由 sunnyfun 于 2008-12-3 10:18 发表
其实搞来搞去是楼主的数据模型设计的有问题,完全可以独立建个好友关系表,将in用表连接替换掉,简单的多对多罢了。



这个问题是多对多关系没错,我这个系统有好友关系表呀,要不怎么取出某个用户的好友呢,望能详细描述您认为的设计模型,多谢指教

论坛徽章:
0
33 [报告]
发表于 2008-12-03 13:45 |只看该作者
原帖由 meizhe1981 于 2008-12-3 11:00 发表



这个问题是多对多关系没错,我这个系统有好友关系表呀,要不怎么取出某个用户的好友呢,望能详细描述您认为的设计模型,多谢指教


假设
用户表为 users, 主键为 userid
好友关系表为 friends 联合主键为 userid, friend_userid
则可以写作

select b.* from
friends a, users b
where a.userid = 某人id
and a.friend_userid = b.userid
order by b.inverse asc


然后优化,没啥特殊的东西吧

[ 本帖最后由 sunnyfun 于 2008-12-3 14:05 编辑 ]

论坛徽章:
0
34 [报告]
发表于 2008-12-03 14:13 |只看该作者
假设
用户表为 users, 主键为 userid
好友关系表为 friends 联合主键为 userid, friend_userid
则可以写作

select b.* from
friends a, users b
where a.userid = 某人id
and a.friend_userid = b ...



按照您说的办法我构建测试数据表结构如下:

  1. /*
  2. SQLyog Enterprise - MySQL GUI v6.0
  3. Host - 5.1.26-rc-community : Database - test
  4. *********************************************************************
  5. Server version : 5.1.26-rc-community
  6. */

  7. /*!40101 SET NAMES utf8 */;
  8. /*!40101 SET SQL_MODE=''*/;
  9. create database if not exists `test`;
  10. USE `test`;
  11. /*!40014 SET @OLD_FOREIGN_KEY_CHECKS=@@FOREIGN_KEY_CHECKS, FOREIGN_KEY_CHECKS=0 */;
  12. /*!40101 SET @OLD_SQL_MODE=@@SQL_MODE, SQL_MODE='NO_AUTO_VALUE_ON_ZERO' */;
  13. /*Table structure for table `friend` */
  14. DROP TABLE IF EXISTS `friend`;
  15. CREATE TABLE `friend` (
  16.   `uid` bigint(20) NOT NULL,
  17.   `fid` bigint(20) NOT NULL,
  18.   PRIMARY KEY (`uid`,`fid`)
  19. ) ENGINE=InnoDB DEFAULT CHARSET=latin1;
  20. /*Data for the table `friend` */
  21. insert  into `friend`(`uid`,`fid`) values (1,2),(1,3),(1,4),(1,5),(1,6);
  22. /*Table structure for table `track` */
  23. DROP TABLE IF EXISTS `track`;
  24. CREATE TABLE `track` (
  25.   `uid` bigint(20) NOT NULL,
  26.   `trackid` bigint(20) NOT NULL,
  27.   `inverse` bigint(20) DEFAULT NULL,
  28.   PRIMARY KEY (`uid`,`trackid`)
  29. ) ENGINE=InnoDB DEFAULT CHARSET=latin1;
  30. /*Data for the table `track` */
  31. insert  into `track`(`uid`,`trackid`,`inverse`) values (2,1,-10),(2,2,-11),(2,3,-12),(3,1,-13),(3,4,-14),(3,6,-15),(4,1,-8),(5,6,-7);
  32. /*Table structure for table `user` */
  33. DROP TABLE IF EXISTS `user`;
  34. CREATE TABLE `user` (
  35.   `uid` bigint(20) NOT NULL AUTO_INCREMENT,
  36.   PRIMARY KEY (`uid`)
  37. ) ENGINE=InnoDB AUTO_INCREMENT=7 DEFAULT CHARSET=latin1;
  38. /*Data for the table `user` */
  39. insert  into `user`(`uid`) values (1),(2),(3),(4),(5),(6);
  40. /*!40101 SET SQL_MODE=@OLD_SQL_MODE */;
  41. /*!40014 SET FOREIGN_KEY_CHECKS=@OLD_FOREIGN_KEY_CHECKS */;
复制代码


查询语句如下:
select t.uid,t.trackid from user as u, friend as f, track as t where u.uid = f.uid and f.fid = t.uid order by t.inverse;


explain结果如下:

  1.    id  select_type  table   type    possible_keys  key      key_len  ref           rows  Extra                                       
  2. ------  -----------  ------  ------  -------------  -------  -------  ----------  ------  --------------------------------------------
  3.      1  SIMPLE       f       index   PRIMARY        PRIMARY  16       (NULL)          5  Using index; Using temporary; Using filesort
  4.      1  SIMPLE       u       eq_ref  PRIMARY       PRIMARY  8        test.f.uid       1  Using index                                 
  5.      1  SIMPLE       t       ref     PRIMARY         PRIMARY  8        test.f.fid        1                                             
复制代码


如何优化掉那个filesort?请指教

论坛徽章:
0
35 [报告]
发表于 2008-12-03 18:17 |只看该作者
explain结果中friend as f 表的 ref 列是NULL 啊;
因为你只建了PRIMARY KEY (`uid`,`fid`)这个组合key,
所以f.fid = t.uid 这里的f.fid 用不到索引;

[ 本帖最后由 simeiren 于 2008-12-3 18:19 编辑 ]

论坛徽章:
0
36 [报告]
发表于 2008-12-03 18:51 |只看该作者
原帖由 simeiren 于 2008-12-3 18:17 发表
explain结果中friend as f 表的 ref 列是NULL 啊;
因为你只建了PRIMARY KEY (`uid`,`fid`)这个组合key,
所以f.fid = t.uid 这里的f.fid 用不到索引;



那您有何高见?

论坛徽章:
0
37 [报告]
发表于 2008-12-03 22:05 |只看该作者


  1. --
  2. -- 数据库: `test`
  3. --

  4. -- --------------------------------------------------------

  5. --
  6. -- 表的结构 `friend`
  7. --

  8. DROP TABLE IF EXISTS `friend`;
  9. CREATE TABLE `friend` (
  10.   `uid` bigint(20) NOT NULL default '0',
  11.   `fid` bigint(20) NOT NULL default '0',
  12.   PRIMARY KEY  (`uid`,`fid`),
  13.   KEY `fid` (`fid`)
  14. ) ENGINE=InnoDB DEFAULT CHARSET=latin1;

  15. --
  16. -- 表中的数据 `friend`
  17. --

  18. INSERT INTO `friend` VALUES (1, 2);
  19. INSERT INTO `friend` VALUES (1, 3);
  20. INSERT INTO `friend` VALUES (1, 4);
  21. INSERT INTO `friend` VALUES (1, 5);
  22. INSERT INTO `friend` VALUES (1, 6);

  23. -- --------------------------------------------------------

  24. --
  25. -- 表的结构 `track`
  26. --

  27. DROP TABLE IF EXISTS `track`;
  28. CREATE TABLE `track` (
  29.   `uid` bigint(20) NOT NULL default '0',
  30.   `trackid` bigint(20) NOT NULL default '0',
  31.   `inverse` bigint(20) default NULL,
  32.   KEY `inverse` (`inverse`)
  33. ) ENGINE=InnoDB DEFAULT CHARSET=latin1;

  34. --
  35. -- 表中的数据 `track`
  36. --

  37. INSERT INTO `track` VALUES (2, 1, -10);
  38. INSERT INTO `track` VALUES (2, 2, -11);
  39. INSERT INTO `track` VALUES (2, 3, -12);
  40. INSERT INTO `track` VALUES (3, 1, -13);
  41. INSERT INTO `track` VALUES (3, 4, -14);
  42. INSERT INTO `track` VALUES (3, 6, -15);
  43. INSERT INTO `track` VALUES (4, 1, -8);
  44. INSERT INTO `track` VALUES (5, 6, -7);

  45. -- --------------------------------------------------------

  46. --
  47. -- 表的结构 `user`
  48. --

  49. DROP TABLE IF EXISTS `user`;
  50. CREATE TABLE `user` (
  51.   `uid` bigint(20) NOT NULL auto_increment,
  52.   PRIMARY KEY  (`uid`)
  53. ) ENGINE=InnoDB DEFAULT CHARSET=latin1 AUTO_INCREMENT=7 ;

  54. --
  55. -- 表中的数据 `user`
  56. --

  57. INSERT INTO `user` VALUES (1);
  58. INSERT INTO `user` VALUES (2);
  59. INSERT INTO `user` VALUES (3);
  60. INSERT INTO `user` VALUES (4);
  61. INSERT INTO `user` VALUES (5);
  62. INSERT INTO `user` VALUES (6);

  63. -- --------------------------------------------------------

  64. EXPLAIN SELECT t.uid, t.trackid
  65. FROM user AS u, friend AS f, track AS t
  66. WHERE u.uid = f.uid
  67. AND f.fid = t.uid
  68. ORDER BY t.inverse;
复制代码




+----+-------------+-------+--------+---------------+---------+---------+------------+------+-------------+
| id | select_type | table | type   | possible_keys | key     | key_len | ref        | rows | Extra       |
+----+-------------+-------+--------+---------------+---------+---------+------------+------+-------------+
|  1 | SIMPLE      | t     | index  | NULL          | inverse |       9 | NULL       |    8 |             |
|  1 | SIMPLE      | f     | ref    | PRIMARY,fid   | fid     |       8 | test.t.uid |    1 | Using index |
|  1 | SIMPLE      | u     | eq_ref | PRIMARY       | PRIMARY |       8 | test.f.uid |    1 | Using index |
+----+-------------+-------+--------+---------------+---------+---------+------------+------+-------------+
3 rows in set (0.00 sec)


[ 本帖最后由 sunnyfun 于 2008-12-4 09:13 编辑 ]

论坛徽章:
10
CU大牛徽章
日期:2013-09-18 15:20:48程序设计版块每日发帖之星
日期:2016-07-21 06:20:00IT运维版块每日发帖之星
日期:2015-07-30 09:40:01技术图书徽章
日期:2014-10-14 16:00:43天蝎座
日期:2013-09-27 17:41:29CU大牛徽章
日期:2013-09-18 15:21:17CU大牛徽章
日期:2013-09-18 15:21:12CU大牛徽章
日期:2013-09-18 15:21:06CU大牛徽章
日期:2013-09-18 15:20:58每日论坛发贴之星
日期:2016-07-21 06:20:00
38 [报告]
发表于 2008-12-04 08:16 |只看该作者
原帖由 meizhe1981 于 2008-12-1 14:29 发表
这张表里存储了所有用户的所有entryid,inverse 记录了一个时间按戳乘 -1 的整数值,也就是一个倒排索引字段,每个用户都要取出自己好友的entryid,并按时间倒排序

inverse 的值既然是有序的,为什么不用一个自增的字段来实现呢?用这个自增的字段来作主键,排序用时就很少了。

论坛徽章:
0
39 [报告]
发表于 2008-12-04 10:02 |只看该作者
select * from t where id=1
union
select * from t where id=2;
union写错没?
再针对union的结果集进行order by a
建立复合索引(a,id)

论坛徽章:
0
40 [报告]
发表于 2008-12-04 10:54 |只看该作者

回复 #1 meizhe1981 的帖子

用USD_INDEX强制mysql 用index看看?
您需要登录后才可以回帖 登录 | 注册

本版积分规则 发表回复

  

北京盛拓优讯信息技术有限公司. 版权所有 京ICP备16024965号-6 北京市公安局海淀分局网监中心备案编号:11010802020122 niuxiaotong@pcpop.com 17352615567
未成年举报专区
中国互联网协会会员  联系我们:huangweiwei@itpub.net
感谢所有关心和支持过ChinaUnix的朋友们 转载本站内容请注明原作者名及出处

清除 Cookies - ChinaUnix - Archiver - WAP - TOP