PHP 板


LINE

看板 PHP  RSS
※ 引述《DarkKiller (System hacked)》之铭言: : 我居然认真写完了,测试报告都没写这麽详细... =_= : ※ 引述《sunlights (sunlights)》之铭言: : : 当时的环境是mssql : : (mysql我没有测过..但是当时资料笔数大概快5万笔..现在己经10几快20万) : : A表放的是调查者的姓名和姓别,B放填写统计表的项目(共有20笔复选) : : 分别以b1,b2,b3...b20个栏位代表,栏位型态tinyint,有选为1,没有选为0 : # 使用者:使用者可以建立问卷,也可以回答问卷 : CREATE TABLE user ( : id INT UNSIGNED PRIMARY KEY AUTO_INCREMENT, : realname VARCHAR(255), : gender TINYINT UNSIGNED : ); : # 问卷 : CREATE TABLE report ( : id INT UNSIGNED PRIMARY KEY AUTO_INCREMENT, : user_id INT UNSIGNED : ); : # 问题 : CREATE TABLE question ( : id INT UNSIGNED PRIMARY KEY AUTO_INCREMENT, : description TEXT : ); : # 一份问卷有很多问题 : CREATE TABLE report_question ( : id INT UNSIGNED PRIMARY KEY AUTO_INCREMENT, : report_id INT UNSIGNED, : question_id INT UNSIGNED : ); : # 一个使用者对於一个问题有一个答案 : CREATE TABLE answer ( : id INT UNSIGNED PRIMARY KEY AUTO_INCREMENT, : question_id INT UNSIGNED, : user_id INT UNSIGNED, : answer TINYINT UNSIGNED : ); : : 要做出 : : b1 b2 b3............b20 : : --------------------------------------- : : 男 : : 女 : SELECT question_id, gender, COUNT(*) : FROM answer : LEFT JOIN user ON answer.user_id = user.id : WHERE question_id IN (SELECT question_id FROM report_question WHERE report_id = ?) : GROUP BY question_id, gender; : 写得有点随便,不过应该意思有到... : : 那时是用 : : select count(*) from A left join b on A.pid=b.pid where A.sex='F' and b.b1=1 : : select count(*) from A left join b on A.pid=b.pid where A.sex='M' and b.b1=1 : : select count(*) from A left join b on A.pid=b.pid where A.sex='F' and b.b2=1 : : select count(*) from A left join b on A.pid=b.pid where A.sex='M' and b.b2=1 : : ...... : : select count(*) from A left join b on A.pid=b.pid where A.sex='F' and b.b20=1 : : select count(*) from A left join b on A.pid=b.pid where A.sex='M' and b.b20=1 : 这可以看 https://en.wikipedia.org/wiki/Database_index 这边讲到的 Index : architecture,这跟资料库能提供的 index 架构有关。 : : pid是帐号 : : 结果跑到快吐血.. : 是效能太差,还是写 40 条觉得很麻烦? : : 後来直接select index 栏位用php去run 才OK : : 我现在都找不到用sql解决的方法.. : : 欢迎大家尝试.. : 前面提到的十万不知道是什麽,我就当作十万个使用者,而且 user 都有参与吧。 : 塞十万个 user:(跑百万次) : INSERT INTO user (gender) VALUES (ROUND(RAND())); : 产生一个报表: : INSERT INTO report SET id = 1, user_id = 1; : 产生 20 个问题:(从 id = 1 跑到 20) : INSERT INTO question SET id = 1; : 把这 20 个问题绑到报表上:(从 question_id = 1 跑到 20) : INSERT INTO report_question SET report_id = 1, question_id = 1; : 对十万个使用者、二十个问题灌资料:(两百万笔) : INSERT INTO answer SET question_id = 1, user_id = 1, answer = ROUND(RAND()); : 没有其他 index 的情况下 (只有建立表格时提供的 primary key) 是 26 秒: : mysql> SELECT SQL_NO_CACHE question_id, gender, COUNT(*) : FROM answer : LEFT JOIN user ON answer.user_id = user.id : WHERE question_id IN (SELECT question_id FROM report_question WHERE report_id = 1) : GROUP BY question_id, gender; : +-------------+--------+----------+ : | question_id | gender | COUNT(*) | : +-------------+--------+----------+ : | 1 | 0 | 50172 | : | 1 | 1 | 49828 | : [...] : +-------------+--------+----------+ : 40 rows in set (26.43 sec) : 这样算快吗?我不知道... 不过这是极限状况,很少有一张问卷超过一万人填 XD : 接下来改 DB schema: : ALTER TABLE answer ADD COLUMN (gender TINYINT UNSIGNED); : 把本来的 gender 塞进去:(跑十万次,从 id = 1 到 id = 100000) : UPDATE answer SET gender = (SELECT gender FROM user WHERE id = 1) WHERE user_id = 1; : 然後把 SELECT 改成: : SELECT SQL_NO_CACHE question_id, gender, COUNT(*) : FROM answer : WHERE question_id IN (SELECT question_id FROM report_question WHERE report_id = 1) : GROUP BY question_id, gender; : 结果是: : 40 rows in set (22.66 sec) : 22 秒,快了一点点,然後补上 index: : CREATE INDEX question_id_gender ON answer (question_id, gender); : 然後重跑: : 40 rows in set (20.95 sec) : 再快了一些... : 然後这边有一个 SQL issue (maybe MySQL only),如果你把 subquery 拆出来自己做 : 就会很快: : SELECT SQL_NO_CACHE question_id, gender, COUNT(*) : FROM answer : WHERE question_id IN (1,2,3,4,5,6,7,8,9,10,11,12,13,14,15,16,17,18,19,20) : GROUP BY question_id, gender; : 速度是: : 40 rows in set (1.09 sec) : 这样能解答你的问题吗?XDDD 谢谢你费心的回答..可是因为当初接手的资料表设计并不是你写的那样 而是 使用者表单 CREATE TABLE user ( id INT UNSIGNED PRIMARY KEY AUTO_INCREMENT, realname VARCHAR(255), sex varchar(2) NOT NULL, city varchar(10) NOT NULL, ....... ); 问卷a ,里面有10几个问题,现在假设是3个问题储存的答案.. a1~a20为复选题1,值是0(没选)或1(有选) b为单选题2,值是A,B,C,D 其中一个 c1~c33为复选题3,值是0(没选)或1(有选) CREATE TABLE answers_a ( id INT UNSIGNED PRIMARY KEY AUTO_INCREMENT, user_id INT UNSIGNED, a1 INT UNSIGNED, a2 INT UNSIGNED, ... a20 INT UNSIGNED, b char(5) NULL, c1 INT UNSIGNED, c2 INT UNSIGNED, ... c33 INT UNSIGNED ); 问卷b,里面有10几个问题..现在假设是4个问题储存的答案.. d1~d7是复选题1,值是0(没选)或1(有选) e 是单选题2,值是 A,B,C,D其中一个 f 是单选题3,值是 1,2,3,4,5,6,7 其中之一 g1~g30是复选题4,值是0(没选)或1(有选) CREATE TABLE answers_b ( id INT UNSIGNED PRIMARY KEY AUTO_INCREMENT, user_id INT UNSIGNED, d1 INT UNSIGNED, d2 INT UNSIGNED, ... d7 INT UNSIGNED, e char(2) NULL, f INT UNSIGNED, g1 INT UNSIGNED, g2 INT UNSIGNED, ... g30 INT UNSIGNED ); 还有问卷c..这里暂时略过.. 为什麽表格是这样的形式...那是客户原来就规划好的..就不讨论了.. 现在要做交叉分析,分别要做 1.使用者表单里的sex和answers_a 里的各项问题答案 2.使用者表单里的sex和answers_b 里的各项问题答案 3.使用者表单里的city和answers_a 里的各项问题答案 4.使用者表单里的city和answers_b 里的各项问题答案 5,answers_a和answers_b的各项问题答案.. 使用者大概20000多人..(因为那个客户是很大的公司) answers_a,answers_b资料笔数大概20多万(现在先以6万来计算就好了).. 所以如果要在最短时间里做出交叉分析..不用PHP跑..用sql跑.. 如何做呢?? 先前有人推文说要加index所以我在想是否所有栏位都要加下去呢?? --



※ 发信站: 批踢踢实业坊(ptt.cc)
◆ From: 111.240.17.176
1F:推 cjoe:看你愿不愿意空间换时间罗~ 11/05 19:06
2F:→ cjoe:不过这边应该要正规划才对,如果问题是固定20个 那就算了 11/05 19:06
3F:→ tyf99:sql 弄个 index,效能会快非常多,我亲身体验,快几百倍有吧 11/06 18:03
4F:推 sadle:SELECT sex, SUM(a.a1) as a1, ..., SUM(a.a3) as a3, 11/09 01:25
5F:→ sadle: SUM(IF(a.b=='a',1,0)) as b_a, ..., 11/09 01:26
6F:→ sadle: SUM(IF(a.b=='d',1,0)) as b_d 11/09 01:26
7F:→ sadle:FROM user u, answers_a a 11/09 01:27
8F:→ sadle:WHERE u.id = a.id GROUP BY u.sex; 11/09 01:27
9F:推 sadle:没实际跑过 记得 u.id 和 a.id 要做 index. 11/09 01:31
10F:→ sadle:复选 打勾用 a 方式统计 多答案的单选用 b 方式统计. 11/09 01:33
11F:→ sunlights:谢谢sa大...我测测看..如果能解决我多年来的疑问..感激 11/09 13:55
12F:→ sunlights:不尽了 11/09 13:55







like.gif 您可能会有兴趣的文章
icon.png[问题/行为] 猫晚上进房间会不会有憋尿问题
icon.pngRe: [闲聊] 选了错误的女孩成为魔法少女 XDDDDDDDDDD
icon.png[正妹] 瑞典 一张
icon.png[心得] EMS高领长版毛衣.墨小楼MC1002
icon.png[分享] 丹龙隔热纸GE55+33+22
icon.png[问题] 清洗洗衣机
icon.png[寻物] 窗台下的空间
icon.png[闲聊] 双极の女神1 木魔爵
icon.png[售车] 新竹 1997 march 1297cc 白色 四门
icon.png[讨论] 能从照片感受到摄影者心情吗
icon.png[狂贺] 贺贺贺贺 贺!岛村卯月!总选举NO.1
icon.png[难过] 羡慕白皮肤的女生
icon.png阅读文章
icon.png[黑特]
icon.png[问题] SBK S1安装於安全帽位置
icon.png[分享] 旧woo100绝版开箱!!
icon.pngRe: [无言] 关於小包卫生纸
icon.png[开箱] E5-2683V3 RX480Strix 快睿C1 简单测试
icon.png[心得] 苍の海贼龙 地狱 执行者16PT
icon.png[售车] 1999年Virage iO 1.8EXi
icon.png[心得] 挑战33 LV10 狮子座pt solo
icon.png[闲聊] 手把手教你不被桶之新手主购教学
icon.png[分享] Civic Type R 量产版官方照无预警流出
icon.png[售车] Golf 4 2.0 银色 自排
icon.png[出售] Graco提篮汽座(有底座)2000元诚可议
icon.png[问题] 请问补牙材质掉了还能再补吗?(台中半年内
icon.png[问题] 44th 单曲 生写竟然都给重复的啊啊!
icon.png[心得] 华南红卡/icash 核卡
icon.png[问题] 拔牙矫正这样正常吗
icon.png[赠送] 老莫高业 初业 102年版
icon.png[情报] 三大行动支付 本季掀战火
icon.png[宝宝] 博客来Amos水蜡笔5/1特价五折
icon.pngRe: [心得] 新鲜人一些面试分享
icon.png[心得] 苍の海贼龙 地狱 麒麟25PT
icon.pngRe: [闲聊] (君の名は。雷慎入) 君名二创漫画翻译
icon.pngRe: [闲聊] OGN中场影片:失踪人口局 (英文字幕)
icon.png[问题] 台湾大哥大4G讯号差
icon.png[出售] [全国]全新千寻侘草LED灯, 水草

请输入看板名称,例如:BuyTogether站内搜寻

TOP