大家好
我现在有个需求,就是有个论坛。
论坛要统计各个地区看各种帖子的人数
我现在有一个表,表结构
ID 主键
region  区域
contrey 国家
lang    语言
count   读取的人数
现在我要统计在这个区域下某个区域某个语言的所有人数
我的sql文是
select sum(*) from tablename where region = 6 and contrey = "cn" and lang in ("111111","22222","33333","33333","33333","33333","33333","33333","33333","33333","33333","33333","33333","33333","33333","33333","33333","33333","33333","33333","33333","33333","33333","33333","33333")在in中的元素是不定的,是从页面中选出来的最多的时候是3500多个
数据库中这个表有8w条数据现在用上面的方法(in)很慢,应该在10秒左右,接受不了啊
还希望大家帮忙啊。
对了我用的是mysql

解决方案 »

  1.   

    lang 上建立索引
    region、contrey字段有多少种值?如果多,可以建立
    lang、region、contrey复合索引
      

  2.   

    我估计在lang上建索引的效果不大,甚至会产生反效果,更慢。
    因为从表的结构来看,region 区域、contrey 国家、lang 语言三列肯定是大量的重复,我估计都不会超过50个种类。那从索引的原理看,这都是属于不适合建索引的列。建联合索引可能会好点。楼主表中:count 读取的人数,这一列是什么意思啊?你说“在in中的元素是不定的,是从页面中选出来的最多的时候是3500多个”,这3500多个都是不同的值吗?这点比较关键。不过我看你给的例子,很多雷同啊。
      

  3.   

    就sql语句本身看在lang、region、contrey建复合索引即可。具体要看你整个应用对这个表的使用,和对应sql的使用是否频繁再做出决策。
      

  4.   

    1) create index xxx on tablename(region,contrey,lang)
    2) 优化一下这个in后的数据,太多重复的 "33333" 不如  in ("111111","22222","33333")效率高。
      

  5.   

    谢谢大家的回答
    真是太感激了,对不起我的问题可能没有问好
    1。count 读取的人数,这一列是什么意思啊?
    count数是这个帖子被多少个人读取过。
    因为业务需要我要分析每个帖子被多少个人读取过。并且还要搜集每个国家有多少个人看过这个帖子。
    2。在in中的元素是不定的,是从页面中选出来的最多的时候是3500多个”,这3500多个都是不同的值吗?这点比较关键。不过我看你给的例子,很多雷同啊。
    对不起我写的不对应该是:
    select sum(*) from tablename where region = 6 and contrey = "cn" and lang in ("111111","22222","33333","44444","55555","66666","77777","88888")
    蓝色的部分最多的时候是3500多个。
    3。我现在的表中lang、region、contrey就是复合索引,也很慢阿。
    还希望大家多多帮忙啊
      

  6.   

    贴出以下结果以供分析。explain select sum(*) from tablename where region = 6 and contrey = "cn" and lang in ("111111","22222","33333","33333","33333","33333","33333","33333","33333","33333","33333","33333","33333","33333","33333","33333","33333","33333","33333","33333","33333","33333","33333","33333","33333");
    show index from tablename ;
      

  7.   

    show create table xxx;
    explain sql语句
    贴结果
      

  8.   

    楼上mysql版的三大高手都露面了,本总潜水学习中。
      

  9.   

    1,根据需求1,country这个字段应该建索引。alter tablename add index country (country);
    2,sum(*) 应该改为sum(count)吧。
    3,就8W条数据,10s的查询有点离谱啊。应该放弃联合索引rcl(region,country,language),而选用rc(region,country),当使用rcl时in的结果只能增加IO,还不如根据rc得到所有语言的记录,然后在程序端进行累加。
    4,languge这个字段如果用字符串存储有点浪费空间,建议采用int存储,这样建立索引时会省不少空间的,语言的种类应该是少数吧。
    5,如果在应用中确实需要统计这样的实时性数据,建议采用ajax+memcached来减少服务器的压力。
      

  10.   

    建议换个sql语句..用join和添加索引
      

  11.   

    大家好谢谢大家的回答,这两天一直和客户开会.回来晚了,实在是对不起啊
    CREATE TABLE `etagtest` (
      `ETAGADVERID` int(32) NOT NULL AUTO_INCREMENT,
      `REGION` varchar(15) DEFAULT NULL,
      `CONTREY` varchar(100) DEFAULT NULL,
      `LANG` varchar(50) DEFAULT NULL,
      `COUNT` int(32) DEFAULT NULL,
      `UPDATEID` int(32) DEFAULT NULL,
      `UPDATEDATE` date DEFAULT NULL,
      PRIMARY KEY (`ETAGADVERID`),
      KEY `fk_RETAGADVER` (`REGION`,`CONTREY`,`LANG`)
    ) ENGINE=InnoDB AUTO_INCREMENT=16670 DEFAULT CHARSET=utf8;执行语句:
    select sum(`COUNT`) from etagtest where LANG in ('00000001','00000002','00000003','00000004',...,'00003099','00003100')
    内容太长了,我贴不全就省略了一些部分。+----+-------------+------------+------+---------------+------+---------+------+
    -------+-------------+
    | id | select_type | table      | type | possible_keys | key  | key_len | ref  |
     rows  | Extra       |
    +----+-------------+------------+------+---------------+------+---------+------+
    -------+-------------+
    |  1 | SIMPLE      | retagadver | ALL  | NULL          | NULL | NULL    | NULL |
     84490 | Using where |
    +----+-------------+------------+------+---------------+------+---------+------+
    -------+-------------+
    1 row in set (0.07 sec)现在速度已经可以了,原因就是我把原来的表索引改称复合索引了但是是这样的:
    我现在没秒100左右的请求,感觉现在的SQL文还是挺慢的,
    SELECT--IN这种检索方式不是比较慢吗,
    各位高手能不能帮帮忙把这个SQL文再优化一下吗?
      

  12.   

    SELECT--IN这种检索方式不是比较慢吗,:有合适的索引,与INNER JOIN区别不大,在硬件、表结构上
    想想办法
      

  13.   

    ("111111","22222","33333",...)
    这些数据是怎么来的呢,如果是表中,直接用 and exists(select 1 from t where conditon) 对条件字段建立索引
    如果是其他方式得来的,增加一个表结构维护这些信息也是可以的。
      

  14.   

    ("111111","22222","33333",...)
    这些数据是怎么来的呢?
    这些数据是从页面中传过来的,本来我也想用exists的但是从页面传过来的都是数值
    所以就放弃了exists
      

  15.   

    \
    可以创建索引的,在3列上创建复合索引,顺序是region ,contrey , lang ,这样他们的唯一性还是很高的,并且只需要维护一个索引,只要前面2个是const  就能利用到此索引,