在几百万数据里查询出适合条件的记录
而且还有关联表,以下是我写的语句,效率太差,想请教高手,还可以怎么改?
SELECT p.author,p.tid, p.authorid,p.dateline, p.message, p.support, p.oppose,t.subject FROM cdb_posts p join cdb_threads t ON p.tid = t.tid AND p.dateline>'$saturday' AND p.dateline<'$friday' AND first=0 AND p.support > 10 group by p.tid ORDER BY p.support DESC LIMIT 20
而且还有关联表,以下是我写的语句,效率太差,想请教高手,还可以怎么改?
SELECT p.author,p.tid, p.authorid,p.dateline, p.message, p.support, p.oppose,t.subject FROM cdb_posts p join cdb_threads t ON p.tid = t.tid AND p.dateline>'$saturday' AND p.dateline<'$friday' AND first=0 AND p.support > 10 group by p.tid ORDER BY p.support DESC LIMIT 20
解决方案 »
- xtrabackup添加--slave-info参数全备失败, InnoDB: Operating system error number 2
- '乗' 这个字为何插入不到数据表里,何解?你遇到过吗?
- mysql 集群 提问
- 两张表查询有重复问题
- 求一条SQL语句。帮帮忙各位。
- 求MYSQL的SQL语句
- Phpmyadmin
- 各位好!我要找一个MYSQL 的客户端进行备份服务器上的数据,那个MYSQL 的确良客户端好用一些呀??
- 可否用MYSQL连接远程SQL Server2000服务器,用什么方法
- 请问一下,Mysql4与Tomcat4已经成功安装了,但怎么样使他们整合起来?
- mysql触发器的两个问题?
- 急求一个触发器
FROM cdb_posts p join cdb_threads t ON p.tid = t.tid
AND p.dateline>'$saturday'
AND p.dateline<'$friday'
AND first=0
AND p.support > 10
group by p.tid
ORDER BY p.support
DESC LIMIT 201. first 来源于哪个表?
2. 为什么要用 group by p.tid ?
3。建议贴出以下信息
show index from cdb_posts;
show index from cdb_threads;
explain SELECT p.author,p.tid, p.authorid,p.dateline, p.message, p.support, p.oppose,t.subject
FROM cdb_posts p join cdb_threads t ON p.tid = t.tid
AND p.dateline>'$saturday'
AND p.dateline<'$friday'
AND first=0
AND p.support > 10
group by p.tid
ORDER BY p.support
DESC LIMIT 20 ;4. 建议描述一想你想实现的功能,及表中数据结构。
这个数据库是discuz的数据库,里面的索引还是默认的,
1、first 来源于cdb_posts
2、我想按p.tid 分组,这样才能实现每种主题贴里只显示一条回复。
Table Non_unique Key_name Seq_in_index Column_name Collation Cardinality Sub_part Packed Null Index_type Comment
cdb_posts 0 PRIMARY 1 pid A 58 NULL NULL BTREE
cdb_posts 1 fid 1 fid A NULL NULL NULL BTREE
cdb_posts 1 authorid 1 authorid A NULL NULL NULL BTREE
cdb_posts 1 dateline 1 dateline A NULL NULL NULL BTREE
cdb_posts 1 invisible 1 invisible A NULL NULL NULL BTREE
cdb_posts 1 displayorder 1 tid A NULL NULL NULL BTREE
cdb_posts 1 displayorder 2 invisible A NULL NULL NULL BTREE
cdb_posts 1 displayorder 3 dateline A NULL NULL NULL BTREE
cdb_posts 1 first 1 tid A NULL NULL NULL BTREE
cdb_posts 1 first 2 first A NULL NULL NULL BTREE Table Non_unique Key_name Seq_in_index Column_name Collation Cardinality Sub_part Packed Null Index_type Comment
cdb_threads 0 PRIMARY 1 tid A 23 NULL NULL BTREE
cdb_threads 1 digest 1 digest A NULL NULL NULL BTREE
cdb_threads 1 sortid 1 sortid A NULL NULL NULL BTREE
cdb_threads 1 displayorder 1 fid A NULL NULL NULL BTREE
cdb_threads 1 displayorder 2 displayorder A NULL NULL NULL BTREE
cdb_threads 1 displayorder 3 lastpost A NULL NULL NULL BTREE
cdb_threads 1 typeid 1 fid A NULL NULL NULL BTREE
cdb_threads 1 typeid 2 typeid A NULL NULL NULL BTREE
cdb_threads 1 typeid 3 displayorder A NULL NULL NULL BTREE
cdb_threads 1 typeid 4 lastpost A NULL NULL NULL BTREE 这是执行explain 后的显示 不过,里面的数据现在很少,因为这是我自己的数据库,不是论坛里的
id select_type table type possible_keys key key_len ref rows Extra
1 SIMPLE p index dateline,displayorder,first first 4 NULL 58 Using where; Using temporary; Using filesort
1 SIMPLE t eq_ref PRIMARY PRIMARY 3 discuz.p.tid 1 我要实现的功能:
查出从上周六到这周五这个时间段内的数据,并按p.tid 分类,使得每种分类只要出现一条记录就可以了,并且,这条记录还不能是第一贴,(first=0)关联另一张表查出分类的另一字段,主题贴标题,最后按support降序排列。
现在的时间比较好还是用between $saturday and $friday 好?
between 和或者直接 > < ,没什么差别。
AND p.first=0
AND p.support > 10
group by p.tid
ORDER BY p.support 这里主要涉及 dateline,first,support,tid 四列数据的索引安排。
如果创建索引,要看你的数据分布。比如你估计全表数据会有多少条?
p.dateline>'$saturday' AND p.dateline<'$friday' 会有多少条?
p.first=0 的会有多少条?
p.support > 10 的会有多少条?
同一p.tid 下平均会有多少条记录?从目前你的情况来看是用了 (tid,first)这个索引,但一般假设中应该是想办法先用 (dateline) 索引。但具体要了解上面几个问题后才能回答。
,用WINRAR压缩
才能测试
我估算了一下,全表大概671W记录
在那个时间段内的就不会很多
大部分都是first = 0
support > 10 一般不会很多
同一p.tid下的平均记录应该也不会太多,目前最多的差不多1k
cdb_posts 表中记录总数 6,710,000 就算 10,000,000 条记录.
在那个时间段内的就不会很多 ? 不会很多,那就算10 条?!
大部分都是first = 0, 99%的记录都是 first=0 ?
support > 10 一般不会很多, 不会很多是多少 10M 记录中一共最多 50 条support > 10 ?!每个 tid 下估计有记录 1000 条左右? 也就是说表中应该有 10M/1K = 10,000 个不同的 tid ?
我重写一个:
在那个时间段内的大概四五万条
90% 都是first = 0
support > 10 大概占总数的10%
同一p.tid下的平均记录应该也不会太多,目前最多的差不多1k
where p.dateline>'$saturday' AND p.dateline<'$friday' , count(*) = 50,000
where first = 0 , count(*) = 90% * 8,000,000 = 7,200,000
where support > 10 , count(*) = 10% * 8,000,000 = 800,000tid , count(*) = 1,000
select distinct tid = 8,000,000/1,000 = 10,000 个不同的 tid, 取其中 support 最大的 20 个每种分类只要出现一条记录就可以了? 随机取一条?还是取其中 support 最大的一条?
粗步仅以上述信息来看,建议索引 (support,dateline) ,假设suppport 为integer型,估计取值范围 0-40, 这样通过索引可以将数据减少到 10%*50,000 = 5000 条
或者(tid,support,dateline)
对于这句查询语句是不是没办法再改了,只能通过索引来优化了是吧。对了,还有我试了一下,要是把group by 去掉,那查询的记录数只要7W多条就可以了,加上分组后就变成了整表查询了,这个跟tid有没有建索引有关系吗?因为我现在不方便修改数据结构,所以想尽量通过修改查询语句来实现,实在不行,那我想就只能先不分组的查询,然后在程序里实现分组筛选工作,麻烦也只能麻烦一点了。
from (select tid,author,tid, authorid,dateline, message, support, oppose
from cdb_posts
where p.dateline>'$saturday' AND p.dateline<'$friday')p , cdb_threads t
where p.tid = t.tid
AND p.first=0
and p.support > 10
group by p.tid
ORDER BY p.support
DESC LIMIT 20先试一下效果如何。优化要很有耐心,在多种方案中进行选择。 你可以先通过子查询来人为的确定筛选的先后顺序。没有你具体的数据,很难进行分析。
SELECT p.author,p.tid, p.authorid,p.dateline, p.message, p.support, p.oppose,t.subject
from (select tid,author,tid, authorid,dateline, message, support, oppose
from cdb_posts p
where p.support > 10 )p , cdb_threads t
where p.tid = t.tid
AND p.first=0
and p.dateline>'$saturday' AND p.dateline<'$friday'group by p.tid
ORDER BY p.support
DESC LIMIT 20
然后再把别的条件放到子查询中,再看一下,哪个的效果最好是不是?
原理是不是应该把记录数最少的条件当做子查询?这样查询的效率才最高?