不等于条件的优化。

peng2739956 2019-03-13 10:45:03
现在有个1000W的表,然后有个视图需要和这个表进行一个联合查询。条件就一个这个1000W需要过滤一个不等于0的字段。我top 100 结果需要2秒钟。是否能进行优化处理。之前有人分享说可以通过WITH 来实现一个优化。具体没说出来。
在这各位能否讨论这个该如何去优化。

SELECT * FROM A LEFT JOIN B ON A.ID=B.ID LEFT JOIN C....
WHERE B.COR<>0

其中A和B的数据量 均为1000W以上。
...全文
1424 17 打赏 收藏 转发到动态 举报
写回复
用AI写文章
17 条回复
切换为时间正序
请发表友善的回复…
发表回复
peng2739956 2019-03-15
  • 打赏
  • 举报
回复
引用 14 楼 吉普赛的歌 的回复:
A,B,C,D,E 这5个表各有多大?

A,D表各是1000W的数据量,CBE 20W数据量
索引 DrawID,InsertTime 这2个索引
Sore也加了索引,但是执行计划并不会执行这个索引
weixin_44749415 2019-03-15
  • 打赏
  • 举报
回复
分析一下查询结果多少,如果比较少,可以独立查询 先查B中COR>0 union COR<0的 这应该走索引,非常快。 然后对结果循环查询A,根据ID,索引查询,也非常快 如果查询结果数据量比较大,就用原来的join语句,把不等于0改成>0 or < 0 试一试
吉普赛的歌 2019-03-15
  • 打赏
  • 举报
回复
--加一个索引:
create index ix_RecordDrawScore_DrawID_Filter on RecordDrawScore(DrawID) where (Score != 0)
go

--查询代码美化一下
SELECT A.DrawID,
       A.KindID,
       A.ServerID,
       A.TableID,
       A.UserCount,
       A.AndroidCount,
       A.Waste,
       A.Revenue,
       A.UserMedal,
       A.StartTime,
       A.ConcludeTime,
       A.InsertTime,
       B.KindName,
       C.ServerName,
       D .Score      AS Score,
       d .BackScore  AS BackScore,
       D .BackInsureScore,
       E.gameid,
       E.accounts,
       E.nickname,
       D .changeIp   AS lastlogonip,
       E.LastLogonType,
       E.userID
FROM   [QPTreasureDB].[dbo].RecordDrawInfo AS A
       LEFT JOIN QPPlatformDB.dbo.GameKindItem AS B
            ON  A.KindID = B.KindID
       LEFT JOIN QPPlatformDB.dbo.GameRoomInfo AS C
            ON  A.ServerID = C.ServerID
       JOIN QPTreasureDB.dbo.RecordDrawScore AS D
            ON  A.DrawID = D .DrawID
       LEFT JOIN QPAccountsDB.dbo.AccountsInfo AS E
            ON  D .UserID = E.userID
WHERE  d .Score != 0
       AND a.InsertTime >= DATEADD(dd, - 7, GETDATE())
ORDER BY
       a.InsertTime DESC
吉普赛的歌 2019-03-14
  • 打赏
  • 举报
回复
A,B,C,D,E 这5个表各有多大?
qq_41327902 2019-03-14
  • 打赏
  • 举报
回复
inserttime有加索引吗?我看你的inserttime是最近7小时的数据,你最近7小时也有1000W数据吗?
还有对于int值的不等于,数据库是会优化成大于
or小于两部分的,所以应该不是这个!=0的问题,又或者你大部分数据都是非0,那么你找出来的数据量很大,慢就可以理解了
纳尼刘君 2019-03-14
  • 打赏
  • 举报
回复
不是有说,N表关联,理论上说至少要分析N!次么.. ,你这5个表关联.. 数据量还大,感觉优化也只是皮毛了
  • 打赏
  • 举报
回复
引用 10 楼 peng2739956 的回复:
[quote=引用 9 楼 好奇都是要学的 的回复:] 1、 A B 数据 是对称的不, 如果 指定对称 把LEFT 换成 INNER , 2、在关联的时候 就排序 不为0的, 而不是关联后在排序 部位0 SELECT * FROM A inner JOIN B ON A.ID=B.ID and B.COR<>0 LEFT JOIN C.... 或者换个 cross apply SELECT * FROM A cross apply (select * from b where B.COR<>0) LEFT JOIN C.... 但是我觉得cross apply 没有 inner join 快, 如果是分组 取 top 或者 分组取最大值 最小值 什么的 比较好用。 得多写几个方法 然后看执行计划 在优化
inner join 会查出脏数据[/quote] 这个要看 具体了, 我说的只是优化的可能
peng2739956 2019-03-13
  • 打赏
  • 举报
回复
引用 6 楼 吉普赛的歌 的回复:
把 on 的条件也贴出来吧

SELECT A.DrawID, A.KindID, A.ServerID, A.TableID, A.UserCount, A.AndroidCount, A.Waste, A.Revenue, A.UserMedal, A.StartTime, A.ConcludeTime, A.InsertTime, B.KindName, C.ServerName, D .Score AS Score, d .BackScore AS BackScore, D .BackInsureScore, E.gameid, E.accounts, E.nickname,D .changeIp AS lastlogonip, E.LastLogonType, E.userID
FROM [QPTreasureDB].[dbo].RecordDrawInfo AS A LEFT JOIN
QPPlatformDB.dbo.GameKindItem AS B ON A.KindID = B.KindID LEFT JOIN
QPPlatformDB.dbo.GameRoomInfo AS C ON A.ServerID = C.ServerID JOIN
QPTreasureDB.dbo.RecordDrawScore AS D ON A.DrawID = D .DrawID LEFT JOIN
QPAccountsDB.dbo.AccountsInfo AS E ON D .UserID = E.userID
WHERE d .Score != 0 AND a.InsertTime >= DateADD(dd, - 7, getdate())
ORDER BY a.InsertTime DESC

执行计划里面93%的开销来自于 d.score
吉普赛的歌 2019-03-13
  • 打赏
  • 举报
回复
把 on 的条件也贴出来吧
peng2739956 2019-03-13
  • 打赏
  • 举报
回复
最关键的是 这个字段的条件是不等于,那么索引其实是无效的,他会进行表扫描,就跟><一样会进行表扫描。
peng2739956 2019-03-13
  • 打赏
  • 举报
回复
引用 3 楼 Dear SQL 的回复:
1。先取出关键表中字段放临时表再其它表关联
2。a,b表字段ID上加索引,b表COR加索引没有?
3。union all 改写where 条件使可以走索引查询
3。不要select * ,取要的字段

A和B 表的ID 都有索引。 COR 也有索引。SELECT * 这个只是方便观看。实际的SQL 取的是相应的字段。
Dear SQL(燊) 2019-03-13
  • 打赏
  • 举报
回复
1。先取出关键表中字段放临时表再其它表关联 2。a,b表字段ID上加索引,b表COR加索引没有? 3。union all 改写where 条件使可以走索引查询 3。不要select * ,取要的字段
Dear SQL(燊) 2019-03-13
  • 打赏
  • 举报
回复
1。先取出关键表中字段再其它表关联 2。a,b表字段ID上加索引,b表COR加索引没有? 3。union all 改写where 条件使可以走索引查询 3。不要select * ,取要的字段
peng2739956 2019-03-13
  • 打赏
  • 举报
回复
补充一下 COR已经有建立索引。但是不等于这个条件 会全表扫描,执行计划 并没有执行这个索引
peng2739956 2019-03-13
  • 打赏
  • 举报
回复
引用 9 楼 好奇都是要学的 的回复:
1、 A B 数据 是对称的不, 如果 指定对称 把LEFT 换成 INNER ,
2、在关联的时候 就排序 不为0的, 而不是关联后在排序 部位0
SELECT * FROM A
inner JOIN B ON A.ID=B.ID and B.COR<>0
LEFT JOIN C....

或者换个 cross apply
SELECT * FROM A
cross apply (select * from b where B.COR<>0)
LEFT JOIN C....
但是我觉得cross apply 没有 inner join 快, 如果是分组 取 top 或者 分组取最大值 最小值 什么的 比较好用。

得多写几个方法 然后看执行计划 在优化

inner join 会查出脏数据
  • 打赏
  • 举报
回复
1、 A B 数据 是对称的不, 如果 指定对称 把LEFT 换成 INNER , 2、在关联的时候 就排序 不为0的, 而不是关联后在排序 部位0 SELECT * FROM A inner JOIN B ON A.ID=B.ID and B.COR<>0 LEFT JOIN C.... 或者换个 cross apply SELECT * FROM A cross apply (select * from b where B.COR<>0) LEFT JOIN C.... 但是我觉得cross apply 没有 inner join 快, 如果是分组 取 top 或者 分组取最大值 最小值 什么的 比较好用。 得多写几个方法 然后看执行计划 在优化
peng2739956 2019-03-13
  • 打赏
  • 举报
回复
最关键的是 这个score 会进行表扫描 就很烦了。我在能用什么方法让他不进行表扫描。

27,579

社区成员

发帖
与我相关
我的任务
社区描述
MS-SQL Server 应用实例
社区管理员
  • 应用实例社区
加入社区
  • 近7日
  • 近30日
  • 至今
社区公告
暂无公告

试试用AI创作助手写篇文章吧