0
Posted on Wednesday, July 05, 2017 by 醉·醉·鱼 and labeled under
最近数据库服务器很慢,跑了一下whoIsActive,发现有很多waittype是RESOURCE_SEMAPHORE,发现很是好玩,整理一下。

一个成功的查询操作会引入3个内存的使用,即查询语句的编译,查询计划的缓存以及数据的缓存。

如何查看编译需要的内存,数据缓存,以及cached plan size

    1. 通过Actual query plan是最快的方法。第一个就是cached plan size(KB), 此外还有CompileMemory(B)和MemoryGrantInfo下的GrantedMemory(KB)。
    2. 在执行计划中查看
    3. 用SQL profiler捕获show plan XML for query compile event,进而在XML查看。其实拿到的数据和第二步一样。

如何模拟RESOURCE_SEMAPHORE

    1. https://www.brentozar.com/archive/2013/08/query-plans-what-happens-when-row-estimates-get-high/ 上例举了两个query。在SSMS里面,多开几个窗口,同时跑第二个query就行了。

RESOURCE_SEMAPHORE情况下,有哪些有趣的数据

    1. sp_whoIsActive 执行sp_whoIsActive 就可以直观看到哪个session已经相应的query
    2. sys.dm_exec_query_resource_semaphores 可以看到当前的内存情况
    3. sys.dm_exec_query_memory_grants 可以看到session获取内存的情况

RESOURCE_SEMAPHORE情况下,所有query都会suspend么?

    1. 不会。如果你的query还是像Brent Ozar提到的第二个query一样需要很多的内存,那就妥妥地等着吧。如果你的query需要的内存很少,那SQL server会直接执行。

引用

https://www.brentozar.com/archive/2013/08/query-plans-what-happens-when-row-estimates-get-high/
https://blogs.msdn.microsoft.com/sqlqueryprocessing/2010/02/16/understanding-sql-server-memory-grant/
0
Posted on Friday, June 09, 2017 by 醉·醉·鱼 and labeled under
熊在微信上找我,问解数独的三种方法。我第一反应是写段代码去解,就哼哧哼哧地写了。后来才发现,她只是要方法而已,就直接丢给链接过去了。(http://www.conceptispuzzles.com/zh/index.aspx?uri=puzzle/sudoku/techniques

但自己还是把这段代码写完了,试了一下,能够解出唯一结果,如果有多个可能就不行了(暂时把可能性列出来了而已)。
最新代码已经上传到 https://github.com/zhongxiao37/zhongxiao37.github.com/blob/master/sudo/sudo.rb

0
Posted on Monday, May 22, 2017 by 醉·醉·鱼 and labeled under ,
Python 和 C 一样,有形参和实参的概念。但是我用ruby的时候,却没有这样的感觉。我每次都会data = function(data),这样的话,我就不需要去担心到底是传递值还是传递指针。但是,就Ruby而言,传递的是对象的引用。详情可以参考:http://www.iteye.com/topic/1117575




0
Posted on Thursday, May 04, 2017 by 醉·醉·鱼 and labeled under
今天发现个新问题。发现在循环中声明变量并不会reset 变量值。

DECLARE @i INT = 0;

WHILE @i < 10
BEGIN
    DECLARE @b int

    print CONCAT('PREV:', @b)

    SET @b = @i

    PRINT CONCAT('NOW:', @b)

    SET @i = @i+1

END


执行上面的query,你会发现PREV的输出并不一致是空,而是有值的。顺手搜了一下,发现很多人都发现这个问题,但是却没有一个官方文档解释这个。立即创建一个规则去避免这坑。
0
Posted on Wednesday, April 26, 2017 by 醉·醉·鱼 and labeled under
Antlr的全程是ANother Tool for Language Recognition,可以用来实现编程语言的解析。由于项目的需要,最近一个月和同事完成了一个针对TSQL的语法分析,进而创建一些规则去审查代码(连这都自动化掉,我实在是太懒了!)。
Antlr是一个比较老的项目了,最新的版本是4.7。个人觉得,这个项目现在之所以成功,还是因为开源以后,很多人都来贡献Antlr的语法文件。在github上,你可以找到主流编程语言的语法文件(https://github.com/antlr/grammars-v4/)。有了语法文件,你就可以直接通过简单的教程使用Antlr。
我们在使用Antlr的时候,已经有了TSQL.g4文件了。语法不是很完整,但我们可以自己贡献代码去帮助其更加完整。可以预见的是,这些语法文件会越来越完整的。

学习Antlr

最经典的还是这个工具开发者自己写的书《The Definitive ANTLR 4 Reference》。快速入门,可以参考https://tomassetti.me/antlr-mega-tutorial/#working-with-a-listener 以及 http://jakubdziworski.github.io/java/2016/04/01/antlr_visitor_vs_listener.html
此外,中文的可以参考https://dohkoos.gitbooks.io/antlr4-short-course/content/getting-started.html

分析TSQL

这个项目的目的就是分析TSQL,进而审查代码,以便开发避免一些坏的编程习惯。要分析TSQL,我们第一反应都是用正则表达式。很不幸,在这个事情上,正则表达式简直是弱爆了!我找到一个比较成熟的语法分析工具,不过是针对pg数据库的。https://pganalyze.com/blog/parse-postgresql-queries-in-ruby.html。文中作者在无数次尝试以后,也发现正则表达式的无力。
通常,我们会看微软自己有没有开发的工具或者API用来分析TSQL。最好的情况就是SSMS里面有个语法分析的组件单独分离出来使用。其实后来我也找到了这样的工具,叫 microsoft.sqlserver.transactsql.scriptdom。但是后来我们考虑到可能还要支持其他类型的数据库,所以我还是选择了Antlr。
在Github上面找到tsql的语法文件,再按照快速入门的步骤,配置好环境,执行下面的命令,就可以拿到整个语法树了。
antlr4 tsql.g4 && javac *.java && grun tsql tsql_file -gui test.sql

Vistior 和 Listener之争

这只是分析语法的两种不同方式而已,看自己的情况选择。一般来说,如果你只想分析某一个rule以及他下面的rule,可以考虑用Visitor。用Listener的话,可以自动的遍历所有的rule。个人而言,还是喜欢Listener。
比如,我们要求在存储过程中,不能够使用PRINT语句,因为我们不希望存储过程返回除了respond code之外的信息。用Listener的话,我只需要在进入和退出存储过程的时候,设置一个flag。然后再判断所有的PRINT语句,如果当前flag为true,就表明这个PRINT是在存储过程里面。


0
Posted on Monday, February 27, 2017 by 醉·醉·鱼 and labeled under
计算某列的和,可以直接用SUM。但如果和SIGN结合起来,事情就有可能复杂了。比如,SUM可以替换成下面一行


SUM((1 - SIGN(Amount)) * Amount / 2) + SUM((1 + SIGN(Amount)) * Amount / 2)

其中,前一部分是算所有正数和,比CASE WHEN 巧妙。

SELECT SUM((1 + SIGN(Amount)) * Amount / 2)

后一部分是算负数和的绝对值。

SELECT SUM((1 - SIGN(Amount)) * Amount / 2)

巧妙+巧妙却不一定等于巧妙!

此外,还有求绝对值的和

SUM((1 + SIGN(Amount)) * Amount / 2) - SUM((1 - SIGN(Amount)) * Amount / 2)
0
Posted on Monday, February 27, 2017 by 醉·醉·鱼 and labeled under
如果要计算昨天的时间,第一反应都是

SELECT DATEADD(DAY, -1, GETUTCDATE())

但还有另外一种写法。因为SQL SERVER的base date是1900-01-01,所以,你可以试着写成下面这样,同样可以得到昨天。

SELECT GETUTCDATE() + '1899-12-31'

可能时间长了,大家会免疫这种写法,你还可以改成,1899-12-30,即-2天。


SELECT DATEADD(DAY, 1, GETUTCDATE()) + '1899-12-30'

还可以这样

SELECT GETUTCDATE() - 1