改变一下inner join顺序试试呢?另外现在有哪些索引? tim_spac说的没错,并没有使用表goods_color和goods_size中的其它字段,size_id和color_id在表goods_sku中都有,可以不用join这两个表,除非为了数据一致性或取得相关的其它字段。
| 类别 | Nested Loop | Hash Join | Merge Join |
|---------------------------------------------|
| 使用条件 | 任何条件 | 等值连接(=) | 等值或非等值连接(>,<,=,>=,<=),‘<>’除外 |
| 相关资源 | CPU、磁盘I/O | 内存、临时空间 | 内存、临时空间 |
| 特点 | 当有高选择性索引或进行限制性搜索时效率比较高,能够快速返回第一次的搜索结果。 | 当缺乏索引或者索引条件模糊时,Hash Join比Nested Loop有效。通常比Merge Join快。在数据仓库环境下,如果表的纪录数多,效率高。| 当缺乏索引或者索引条件模糊时,Merge Join比Nested Loop有效。非等值连接时,Merge Join比Hash Join更有效
| 缺点 | 当索引丢失或者查询条件限制不够时,效率很低;当表的纪录数多时,效率低。| 为建立哈希表,需要大量内存。第一次的结果返回较慢。 | 所有的表都需要排序。它为最优化的吞吐量而设计,并且在结果没有全部找到前不返回数据。|
本文所做实验均基于PostgreSQL 935平台
一张记录数1万以下的小表nbarmse_test_test,一张大表165万条记录的大表nbarnbar_test,大表上建有索引
如下图所示,执行器将小表mse_test_test作为外表(驱动表),对于其中的每条记录,通过大表(nbar_test)上的索引匹配相应记录。
如下图所示,执行器选择一张表将其映射成散列表,再遍历另外一张表并从散列表中匹配相应记录。
如下图所示,执行器先分别对mse_test_test和nbar_test按client_key排序。其中mse_test_test使用快速排序,而nbar_test使用external merge排序,之后对二者进行Merge Join。
通过对比 Query 1 Test 1 , Query 1 Test 2 , Query 1 Test 3 可以看出Nested Loop适用于结果集很小(一般要求小于一万条),并且内表在Join字段上建有索引(这点非常非常非常重要)。
如下图所示,执行器通过聚簇索引对大表(nbar_test)排序,直接通过快排对无索引的小表(mse_test_test)排序,之后对二才进行Merge Join。
通过对比 Query 1 Test 3 和 Query 1 Test 4 可以看出,Merge Join的主要开销是排序开销,如果能通过建立聚簇索引(如果Query必须显示排序),可以极大提高Merge Join的性能。从这两个实验可以看出,创建聚簇索引后,查询时间从4956768 ms缩减到了1815238 ms。
如下图所示,执行器通过聚簇索引对大表(nbar_test)和小表(mse_test_test)排序,之后对二才进行Merge Join。
对比 Query 1 Test 4 和 Query 1 Test 5 ,可以看出二者唯一的不同在于对小表(mse_test_test)的访问方式不同,前者使用快排,后者因为聚簇索引的存在而使用Index Only Scan,在表数据量比较小的情况下前者比后者效率更高。由此可看出如果通过索引排序再查找相应的记录比直接在原记录上排序效率还低,则直接在原记录上排序后Merge Join效率更高。
时间与 Query 1 Test 2 几乎相等。
通过对比 Query 1 Test 2 , Query 1 Test 6 可以看出Hash Join不要求表在Join字段上建立索引。
mse_test约100万条记录,nbar_test约165万条记录
本次实验通过设置 enable_hashjoin=true , enable_nestloop=false , enable_mergejoin=false 来试图强制使用Hash Join,但是失败了。
阅读下一篇 SQL优化(二) 快速计算Distinct Count
解决了?
需求看不懂啊
INSERT INTO #temp_tpproj
SELECT top 50 tproj_no
FROM #t_result t
WHERE ttp_n IS NULL
这里取前50条数据,不用排序?随即的? 还是说SYBASE内部自己能排序?
INSERT INTO #tempgltypemje
SELECT gl_type
FROM CISglsrc_type(index glsrc_typeI1)
WHERE source_name = 'MJE'
你这个gl_type有没有重复的?,有重复的下面哪个查询性能就没法要了
1、因为T1表式主表,所以
select COUNT(DISTINCT T1A1) from T1和你求出的
COUNT(DISTINCT T1A1)值是一样的。
2、而由于T2等是从表并且你使用了COUNT(DISTINCT T2B1)因此null值会被排除掉,实际上和下面的语句求出的值是一样的
select COUNT(DISTINCT T2B1) from T1 inner join T2 on T1A1 = T2A1;
3、从上面的分析可以看出你使用left join的目的只有一个就是得到T1表全部数据的COUNT(DISTINCT T1A1),所以试试改成下面的sql是否性能能够快些
select cnt1+cnt2+cnt3 from(
(select COUNT(DISTINCT T1A1) cnt1 from T1 GROUP BY T1A2, T1A3)t1,
(select COUNT(DISTINCT T2B1) cnt2 from T1 inner join T2 on T1A1 = T2A1 GROUP BY T1A2, T1A3)t2,
(select COUNT(DISTINCT T3C1) cnt3 from T1 inner join T3 on T1A1 = T3A1 inner join T4 on T3C1 = T4C1 GROUP BY T1A2, T1A3)t3;
---
以上,希望对你有所帮助。
你这个需求,就是N个表的各自SUM求和,无论用什么语句,从效率上是没法提高的,因为数据运算没法避免。
给你几个参考建议:
左连接是没有必要的,你需要的其实就是不同表各自的sum,应该各自查询就好了
分开语句写,语句更精简
这样的需求,最好使用存储过程和循环语句,在需求上可以更灵活,可以查询任意天数和任意起始日期的数据
当数据量很多(天数积累),并且查询比较频繁的时候,应该引入“中间表”或“临时表”,表中每条记录记录一天的sum值(可以通过存储过程或者定时任务维护),这样再次查询会更有效率。
以上就是关于数据量大表inner join,有办法优化吗全部的内容,包括:数据量大表inner join,有办法优化吗、SQL优化(一) Merge Join VS. Hash Join VS. Nested Loop、sybase sql 多表inner join调优求助等相关内容解答,如果想了解更多相关内容,可以关注我们,你们的支持是我们更新的动力!
欢迎分享,转载请注明来源:内存溢出
评论列表(0条)