的性能会优于散列连接。
原远(Q6):有个问题:分类表TQueCategory,问题表TQuestion(T-SQL)
CREATE TABLE TQueCategory
(
ID INT IDENTITY(1,1) PRIMARY KEY, --问题分类ID
NAME VARCHAR(20) --问题分类名称
)
CREATE TABLE TQuestion
(
ID INT IDENTITY(1,1) PRIMARY KEY, --问题ID
CateID INT NOT NULL, --问题分类ID
TITLE VARCHAR(50), --问题标题
CONTENT VARCHAR(500) --问题内容
)
当前要统计某个分类下的问题数,有两种方式:
1.每次统计,在TQuestion通过CateID进行分组统计
SELECT CateID,COUNT(1) AS QueNum FROM TQuestion GROUP BY CateID WHERE 1=1
2.在TQueCategory表增加字段QueNum,用于标识该分类下的问题数量
ALTER TABLE TQueCategory ADD QueNum INT
SELECT CateID,QueNum FROM TQueCategory
问:在哪种业务应用场景下采用上面哪种方式性能比较好,为什么?
玄惭(A6):方案 一 需要对 TQuestion 的 CateID字段 进行分组 ,可以在CateID上创建一个索引,这样就可以索引扫描来完成查询;
方案 二 需要对 TQueCategory 进行扫描就可以得出结果,但是必须在问题表有插入,删除的时候维护quenum数量;
单单从SQL的性能来看,分类表的数量应该是远远小于问题表的数量的,所以方案二的性能会比较好;
但是如果TQuestion 的插入非常频繁的话,会带来对TQueCategory的频繁更新,一次TQuestion 的insert或deleted就会带来一次TQueCategory 的update,这个代价其实是蛮高的;
如果这个分类统计的查询不是非常频繁的话,建议还是使用方案一;
同时还可能还会其他的业务逻辑统计需求(例如:CateID +时间),这个时候在把逻辑放到TQueCategory就不合适了。
玩站网(Q7):无关技术方面: 咨询一下,现在mysql新的版本,5.5.45后貌似修改了开源协议。 是否意味着今后我们商业化使用mysql将受到限制? 如果甲骨文真周到那一步,rds是否会受到影响? 一个疑惑: 为什么很少见到有人用mysql正则匹配?性能不好还是什么原因?
玄惭(A7):MySQL有商业版 和 社区版,RDS的MySQL采用开源的社区版进行改进,由专门的RDS MySQL源码团队来维护,国内TOP 10的mysql源码贡献者大部分都在RDS,包括了@丁奇 ,@彭立勋 ,@印风 等;
不在数据库中做业务计算,是保证数据库运行稳定的一个好的设计经验;
是否影响性能与你的sql的执行频率,需要参与的计算数据量相关,当然还包括数据库所在主机的IO,cpu,内存等资源,离开了这些谈性能是没有多大意义的。
比哥(Q8):分页该怎么优化才行???
玄惭(A8):可以参考这个链接,里面有很多的最佳实践,其中就包括了分页语句的优化: http://bbs.aliyun.com/read/168647.html
普通写法:
select * from t where sellerid=100 limit 100000,20
普通limit M,N的翻页写法,往往在越往后翻页的过程中速度越慢,原因
mysql会读取表中的前M+N条数据,M越大,性能就越差:
优化写法:
select t1.* from t t1,
(select id from t sellerid=100 limit 100000,20) t2
where t1.id=t2.id;
优化后的翻页写法,先查询翻页中需要的N条数据的主键id,在根据主键id
回表查询所需要的N条数据,此过程中查询N条数据的主键ID在索引中完成
注意:需要在t表的sellerid字段上创建索引
create index ind_sellerid on t(sellerid);
案例:
user_A (21:42:31):
这个sql该怎么优化,执行非常的慢:
| Query | 51 | Sending data |
select id, ... from t_buyer where sellerId = 765922982 and
gmt_modified >= '1970-01-01 08:00:00' and gmt_modified <= '2013-06-05 17:11:31'
limit 255000, 5000
SQL改写:selectt2.* from
(selectid from t_buyer where sellerId = 765922982
andgmt_modified >= '1970-01-01 08:00:00'
andgmt_modified <= '2013-06-05 17:11:31'
limit255000, 5000)t1,t_buyer t2 where t1.id=t2.id
index:seller_id,gmt_modified
user_A(21:58:43):
好像很快啊。神奇,这个原理是啥啊。牛!!!
user_A(21:59:55):
5000 rows in set (4.25 sec),前面要90秒。
板砖大叔(Q9):问个小白的问题,大师建议一般索引类型和索引方法使用哪种,还是说针对不同的逻辑用不同的》?
玄惭(A9):这里所说的索引都是普通的b-tree索引,mysql,sqlserver,oracle 的关系数据库都是默认支持的。
几几届(Q10):我也是这样,简单的会,仔细写也会写出来,但是就是不知道有没有更快或者更好的
玄惭(A10):多写写SQL,掌握SQL优化的方法,自然这些问题不在话下了。
veeeye(Q11):可以详细说明一下“最后建议不要在数据库中使用外键,让应用程序来保证。 ”的原因吗?我们公司在项目中经常使用外键,用程序来保证不是相对而言更加复杂了吗?
玄惭(A11):这里的不建议使用外键,主要考虑到 :
第一.维护成本上,把一些业务逻辑交由数据库来保证,当业务需求发生改动的时候,需要同时考虑应用程序和数据库,有时候一些数据库变更或者bug,可能会导致外键的失效;同时也给数据库的管理人员带来维护的麻烦,不便于管理。
第二.性能上考虑,当大量数据写入的时候,外键肯定会带来一定的性能损耗,当出现这样的问题时候,再来改造去除外键,真的就不值得了;
最后,不在数据库中参与业务的计算(存储过程,函数,触发器,外键),是保证数据库运行稳定的一个好的最佳实践。
优雅的固执(Q12):十分想请大师分享下建立索引的经验,我平时简历索引是这样的,比如订单信息的话,建立,订单号,唯一聚集索引,其他的比如 客户编号 供应商编号 商品编号 这些建立非聚集不唯一索引 仅此而已 想更深入的跟大师学学
玄惭(A12):建立索引,需要根据你的SQL语句来进行创建,不是每一个字段都需要进行创建,也不是一个索引都不创建,,可以把你的SQL语句,应用场景发出来看看。
索引的创建确实是一个非常专业的技术活,需要掌握:表的存储方式,索引的原理,数据库的优化器,统计信息,最后还需要能够读懂数据库的执行计划,以此来判断索引是否创建正确; 所以需要进 |