‘壹’ 急求设计sql语言的语法树
看是用在asp中或是易语言中,abc是变量还是常量,另外是不是模糊查询,这样一来就要分好几种情况了(以下代码不含模糊查询,如果要用需要加%号):
一、abc为常量
不分易语言和asp
如果字段1-4是文本内容,sql语句如下:
"select
*
from
表1
where
字段1
like
'abc'
and
字段2
like
'abc'
and
字段3
like
'abc'
and
字段4
like
'abc'"
如果字段1-4是数值内容,sql语句如下:
"select
*
from
表1
where
字段1=abc
and
字段2=abc
and
字段3=abc
and
字段4=abc"
二、abc为变量
如果字段1-4是文本内容,sql语句如下:
asp中:
“select
*
from
表1
where
字段1
like
'”&abc&"'
and
字段2
like
'”&abc&"'and
字段3
like
'”&abc&"'and
字段4
like
'”&abc&"'"
易语言中:
”select
*
from
表1
where
字段1
like
'“+abc+”'
and
字段2
like
'“+abc+”'
and
字段3
like
'“+abc+”'
and
字段4
like
'“+abc+”'
"
如果字段1-4是数值内容,sql语句如下:
asp中:
“select
*
from
表1
where
字段1
=”&abc&"and
字段2
=”&abc&"and
字段3=”&abc&"and
字段4=”&abc&"
易语言中:
“select
*
from
表1
where
字段1
=”+abc+"and
字段2
=”+abc+"and
字段3=”+abc+"and
字段4=”+abc+"
‘贰’ MySql中Sql的执行过程
如果查询缓存没有命中,那么SQL请求会进入分析器,分析器是用来分辨SQL语句的执行目的,其执行过程大致分为两步:
表1 语法分析关键字然后再通过语法规则解析,判断输入的SQL 语句是否满足MySQL语法,并且生成图5的语法树。由SQL语句生成的四个单词中,识别出两个关键字,分别是select 和from。根据MySQL的语法Select 和 from之间对应的是fields 字段,下面应该挂接username;在from后面跟随的是Tables字段,其下挂接的是userinfo。
优化器的作用是对SQL进行优化,生成最有的执行方案。如图6所示,前面提到的SQL解析器通过语法分析和语法规则生成了SQL语法树。这个语法树作为优化器的输入,而优化器(黄色的部分)包含了逻辑变换和代价优化两部分的内容。在优化完成以后会生成SQL执行计划作为整个优化过程的输出,交给执行器在存储引擎上执行。
所处的位置如上图所示,这节的重点在优化器中的逻辑变换和代价优化上。
逻辑变换也就是在关系代数基础上进行变换,其目的是为了化简,同时保证SQL变化前后的结果一致,也就是逻辑变化并不会带来结果集的变化。其主要包括以下几个方面:
这样讲概念或许有些抽象,通过图7 来看看逻辑变化如何在SQL中执行的吧。
如图7所示,从上往下共有4个步骤:
1. 针对存在的SQL语句,首先通过“否定消除”,去掉条件判断中的“NOT”。语句由原来的“or”转换成“and”,并且大于小于符号进行变号。蓝色部分为修改前的SQL,红色是修改以后的SQL。2. 等值传递,这一步很好理解分别降”t2.a=9” 和”t2.b=5”分别替换掉SQL中对应的值。3. 接下来就是常量表达式计算,将“5+7”计算得到“12”。4. 最后是常量表达式计算后的化简,将”9<=10”化简为”true”带入到最终的SQL表达式中完成优化。
代价优化是用来确定每个表,根据条件是否应用索引,应用哪个索引和确定多表连接的顺序等问题。为了完成代价优化,需要找到一个代价最小的方案。因此,优化器是通过基于代价的计算方法来决定如何执行查询的(Cost-based Optimization)。简化的过程如下:
这里将配置操作的代价分为MySQL 服务层和MySQL 引擎层,MySQL 服务层主要是定义CPU的代价,而MySQL 引擎层主要定义IO代价。MySQL 5.7 引入了两个系统表mysql.server_cost和mysql.engine_cost来分别配置这两个层的代价。如下:MySQL 服务层代价保存在表server_cost中,其具体内容如下:
由上可以看出创建临时表的代价是很高的,尤其是内部的myisam或innodb临时表。MySQL 引擎层代价保存在表engine_cost中,其具体内容如下:
目前io_block_read_cost和memory_block_read_cost默认值均为1,实际生产中建议酌情调大memory_block_read_cost,特别是对普通硬盘的场景。MySQL会根据SQL查询生成的查询计划中对应的操作从上面两张代价表中查找对应的代价值,并且进行累加形成最终执行SQL计划的代价。再将多种可能的执行计划进行比较,选取最小代价的计划执行。
当分析器生成查询计划,并且经过优化器以后,就到了执行器。执行器会选择执行计划开始执行,但在执行之前会校验请求用户是否拥有查询的权限,如果没有权限,就会返回错误信息,否则将会去调用MySQL引擎层的接口,执行对应的SQL语句并且返回结果。例如SQL:“SELECT * FROM userinfo WHERE username = 'Tom';“假设 “username“ 字段没有设置索引,就会调用存储引擎从第一条开始查,如果碰到了用户名字是” Tom“, 就将结果集返回,没有查找到就查看下一行,重复上一步的操作,直到读完整个表或者找到对应的记录。需要注意SQL语句的执行顺序并不是按照书写顺序来的,顺序的定义会在分析器中做好,一般是按照如下顺序:
如果命中的记录比较多,应用会从MySql Server一批批获取数据
本文从MySQL中SQL语句的执行过程作为切入点,首先介绍了查询请求的执行流程,其中将MySQL的处理分为MySQL Server层和MySQL存储引擎层。通过介绍SQL语句的流转,引出了后面要介绍的5大组件,他们分别是:连接器、查询缓存、分析器、优化器、执行器。后面的内容中对每个组件进行了详细的介绍。连接器,负责身份认证和权限鉴别;查询缓存,将查询的结果集进行缓存,提高查询效率;分析器,对SQL语句执行语法分析和语法规则,生成语法树和执行计划;优化器,包括逻辑变换和代价优化;执行器,在检查用户权限以后对数据进行逐条查询,整个过程遵守SQL语句的执行顺序。
‘叁’ 怎样将一个sql语句转化为相应的语法树
token就是把程序的语句进行类似分词得到的单词。
它是下步语法分析的输入。
typedef struct Token
{
int label;
char name[buf];
int code;
}Token;
是一个结构体。
C语言中单词可以分为
保留字,就是int,while等。
标识符,例如int m;m就是标识符。
数字,有整数和小数
字符,+,-,.,*,;等字符,其中也包括++,--,!=等。
label应该标识token的类型。
name表示的就是程序中对应的字符序列。例如:int等。
最后code的意思,看不出来。。。,不过个人认为,上面的两项就可以表示
token的信息。
‘肆’ 如何查看数据库表中的sql语句
两种方式,一种是直接在sqlserver的列表中找到,另一种用写语句的方式查询。
方法一:
1、登陆SQL SERVER Manager Studio。
2、在左边的树找到自己要查询的数据库。如图:
3、点击“表”,就能看到这个库中的所有表了。
方法二:
1、登陆SQL SERVER Manager Studio。
2、点击左上角的“新建查询”。
3、在窗口中编写sql语句如下,然后运行
1
SELECT name FROM SysObjects Where XType='U' ORDER BY Name
结果截图:
‘伍’ 怎么获取执行的sql语句
1、select b.spid,a.sid,a.serial#,a.machine from v$session a,v$process b where a.paddr = b.addr and a.machine='yz';
PID SID SERIAL# MACHINE
9497 49 3406 yz
2、利用10046事件开始跟踪
SQL>execute sys.dbms_system.set_ev(49, 3406,10046,1,'');
PL/SQL procere successfully completed.
、这时候你可以运行应用程序,对于web 应用你就可以打开你认为性能比较差页面。
4、如果你要查看这段时间执行了哪些sql语句,可以执行下面的语句结束跟踪
SQL>execute sys.dbms_system.set_ev(49,3406,10046,0,'');
PL/SQL procere successfully completed.
5、SQL trace 工具会收集这个过程中执行的SQL的性能状态数据,记录到一个跟踪文件中.这个跟踪文件提供了许多有用的信息,例如解析次数.执行次数,CPU使用时间等。
6、这时候你可以通过下面的语句获得产生的跟踪文件所在的目录
SQL> select value from v$parameter where name = 'user_mp_dest';
VALUE
--------------------------------------------------------------------------------
/opt/oracle/admin/ocn/ump
7、在/opt/oracle/admin/ocn/ump下找到yzoracle_ora_9497.trc。9497是你当前应用的spid。
8、注意yzoracle_ora_9497.trc是不可读的,我们需要执行oracle的tkprof命令,将yzoracle_ora_9497.trc转化为我们可读的文本文件。
tkprof yzoracle_ora_9497.trc yzoracle_ora_9497.sql
这样你就可以在yzoracle_ora_9497.sql文件中看到所有的sql语句执行次数,CPU使用时间等数据。
‘陆’ impala怎么解析sql语句
Impala的SQL解析与执行计划生成部分是由impala-frontend(Java)实现的,监听端口是21000。用户通过Beeswax接口BeeswaxService.query()提交一个请求,在impalad端的处理逻辑是由void ImpalaServer::query(QueryHandle& query_handle, const Query& query)这个函数(在impala-beeswax-server.cc中实现)完成的。
在impala中一条SQL语句先后经历BeeswaxService.Query->TClientRequest->TExecRequest,最后把TExecRequest交由impala-coordinator分发给多个backend处理。本文主要讲一条SQL语句是怎么一步一步变成TExecRequest的。
本文以下内容都以这样的一个SQL为例说明:
select jobinfo.dt,user,
max(taskinfo.finish_time-taskinfo.start_time),
max(jobinfo.finish_time-jobinfo.submit_time)
from taskinfo join jobinfo on jobinfo.jobid=taskinfo.jobid
where jobinfo.job_status='SUCCESS' and taskinfo.task_status='SUCCESS'
group by jobinfo.dt,user
通过调用Status ImpalaServer::GetExecRequest(const TClientRequest& request, TExecRequest* result) 函数把TClientRequest转化成TExecRequest
在这个函数里通过JNI接口调用frontend.createExecRequest()生成TExecRequest。首先调用AnalysisContext.analyze(String stmt)分析提交的SQL语句。
注释:Analyzer对象是个存放这个SQL所涉及到的所有信息(包含Table, conjunct, slot,slotRefMap, eqJoinConjuncts等)的知识库,所有跟这个SQL有关的东西都会存到Analyzer对象里面。
1,SQL的词法分析,语法分析
AnalysisContext.analyze(String stmt)会调用SelectStmt.analyze()函数,这个函数就是对SQL的analyze和向中央知识库Analyzer register各种信息。
(1)处理这个SQL所涉及到的Table(即TableRefs),这些Table是在from从句中提取出来的(包含关键字from, join, on/using)。注意JOIN操作以及on/using条件是存储在参与JOIN操作的右边的表的TableRef中并分析的。依次analyze()每个TableRef,向Analyzer注册registerBaseTableRef(填充TupleDescriptor)。如果对应的TableRef涉及到JOIN操作,还要analyzeJoin()。在analyzeJoin()时会向Analyzer registerConjunct()填充Analyzer的一些成员变量:conjuncts,tuplePredicates(TupleId与conjunct的映射),slotPredicates(SlotId与conjunct的映射),eqJoinConjuncts。本例中on从句是一种BinaryPredicate,然后onClause.analyze(analyzer)会递归analyze这个on从句里的各种组件。
(2)处理select从句(包含关键字select, MAX(), AVG()等聚集函数):分析这个SQL都select了哪几项,每一项都是个Expr类型的子类对象,把这几项填入resultExprs数组和colLabels。然后把resultExprs里面的Expr都递归analyze一下,要分析到树的最底层,向Analyzer注册SlotRef等。
(3)分析where从句(关键字where),首先递归Analyze从句中Expr组成的树,然后向Analyzer registerConjunct()填充Analyzer的一些成员变量(同1,此外还要填充whereClauseConjuncts) 。
(4)处理sort相关信息(关键字order by)。先是解析aliases和ordinals,然后从order by后面的从句中提取Expr填入orderingExprs,接着递归Analyze从句中Expr组成的树,最后创建SortInfo对象。
(5)处理aggregation相关信息(关键字group by, having, avg, max等)。首先递归分析group by从句里的Expr,然后如果有having从句就像where从句一样,先是analyze having从句中Expr组成的树,然后向Analyzer registerConjunct()等。
(6)处理InlineView。
关于SQL解析中所涉及到的各种数据结构表示如下:
至此词法分析,语法分析结束,有点像一个小的编译器。我们现在回到frontend.createExecRequest()函数中。调用完AnalysisContext.analyze()之后,就开始填充TExecRequest内的成员变量。
(1)如果是DDL命令(use, show tables, show databases, describe),那么调用createDdlExecRequest();
(2)另外一种情况就是Query或者DML命令,那么就得创建和填充TQueryExecRequest了。
2,根据SQL语法树生成执行计划(PlanNode和PlanFragment的生成)
下面就是用Planner把SQL解析出的语法树转换成Plan fragments,后者能在各个backend被执行。
Planner planner = new Planner();
ArrayListfragments =
planner.createPlanFragments(analysisResult, request.queryOptions);
这个createPlanFragments()函数是frontend最重要的函数:根据SQL解析的结果和client传入的query options,生成执行计划。执行计划是用PlanFragment的数组表示的,最后会序列化到TQueryExecRequest.fragments然后传给backend的coordinator去调度执行。
下面进入Planner.createPlanFragments()函数看看执行计划是怎么生成的:
首先要搞清楚两个概念:PlanNode和PlanFragment。
PlanNode是SQL解析出来的逻辑功能节点;PlanFragment是真正的执行计划节点。
2.1,创建PlanNode
PlanNode singleNodePlan =
createQueryPlan(queryStmt, analyzer, queryOptions.getDefault_order_by_limit());
(1)这个函数首先根据from从句中的第一个TableRef创建一个PlanNode,一般为ScanNode(HdfsScanNode或者HBaseScanNode)。这个ScanNode关联一个ValueRange的数组(由多个cluster column取值区间组成)表示要读取的Table的范围,还关联一个conjunct(where从句)。
(2)这个SQL语句中TableRef中剩下的其他Table就需要建立HashJoinNode了。进入Planner.createHashJoinNode()函数:首先为这个Table建立ScanNode(同上),然后调用getHashLookupJoinConjuncts()获取两表或者多表JOIN的eqJoinConjuncts和eqJoinPredicates,利用这两个条件创建HashJoinNode。每个HashJoinNode也是树状的,会有孩子节点,对于我们举例的两表JOIN,孩子节点分别是两个表对应的ScanNode。(注意目前impala只支持一大一小两个表的JOIN,默认是左大右小,是通过把右边的小表分发到每个节点的内存中分别于左边大表的一个区间进行JOIN过滤实现的。)
(3)如果有group by从句,创建AggregationNode,并把刚才的HashJoinNode设为它的孩子。这里暂时不考虑DISTINCT aggregation function。
(4)如果有order by… limit从句,创建SortNode。
这样createQueryPlan()函数执行完毕,PlanNode组成的execution tree形成如下:
2.2,创建PlanFragment
接下来就看impala backend节点数目有多少,如果只有一个节点,那么整棵执行树都在同一个impalad上执行;否则调用createPlanFragments(singleNodePlan, isPartitioned, false, fragments)把PlanNode组成的执行树转换成PlanFragment组成的执行计划。
下面进入createPlanFragments()这个函数:
这是一个递归函数,沿着PlanNode组成的执行树递归下去,分别创建对应的Fragment。
(1)如果是ScanNode,创建一个PlanFragment(这个PlanFragment的root node是这个ScanNode,而且这个PlanFragment只包含一个PlanNode)。
(2)如果是HashJoinNode,并不是创建一个新的PlanFragment,而是修改leftChildFragment(是一个ScanNode)为以HashJoinNode作为root node的PlanFragment。因为对于HashJoinNode一般有两个ScanNode孩子,在处理HashJoinNode之前已经把这两个ScanNode变成了对应的PlanFragment。那么此时要得到HashJoinNode作为root node的PlanFragment是通过Planner.createHashJoinFragment()函数完成的:首先把当前HashJoinNode作为HashJoinFragment的root node;然后把leftChildFragment中的root PlanNode(也就是参与JOIN的两个表中左边的那个表对应的ScanNode)作为HashJoinNode的左孩子;通过调用Planner.connectChildFragment()函数把HashJoinNode的右孩子设置为一个ExchangeNode(这个ExchangeNode表示一个1:n的数据流的receiver);同时把rightChildFragment(ScanNode作为root node)的destination设置为这个ExchangeNode。
(3)如果是AggregationNode,聚集操作很复杂了。以我们的例子来说明:如果这个AggregationNode不是DISTINCT aggregation的2nd phase(因为本例中的AggregationNode的孩子是HashJoinNode而不是另外一个AggregationNode),首先把刚才生成的HashJoinNode作为root node对应的PlanFragment的root node设置为该AggregationNode,并把原来的root node(即HashJoinNode)设为新root node的孩子。然后通过Planner.createParentFragment()创建一个包含ExchangeNode作为root node的新的PlanFragment。并把孩子PlanFragment的destination设置为这个ExchangeNode。然后在这个新的PlanFragment中创建一个新的AggregationNode作为新的root node并把刚才的ExchangeNode作为其孩子节点。
至此,createPlanFragments()调用完成,生成的三个PlanFragment如下:
通过createPlanFragments(singleNodePlan, isPartitioned, false, fragments)获取了所以执行计划PlanFragment组成的数组fragments,这个数组的最后一个元素就是根节点PlanFragment。然后就是调用PlanFragment.finalize()把这个执行计划finalize(递归finalize每个PlanNode)同时为每个PlanFragment指定 DataStreamSink。
然后回到frontend.createExecRequest()函数中。执行完Planner.createPlanFragments()返回的ArrayList就是完整的执行计划了。然后就是一次调用PlanFragment.toThrift()把它序列化到TQueryExecRequest。填充TQueryExecRequest的相关变量:dest_fragment_idx,per_node_scan_ranges,query_globals,result_set_metadata等。最后返回TExecRequest型的对象给backend执行。
‘柒’ 怎么获取执行的sql语句
方法一:可以通过执行该命令来查看错误日志信息:exec xp_readerrorlog 方法二:在SQL SERVER Management Studio中连接该sql server实例,object Explorer中查找Management->SQL Server logs->右键选view-》选择你要看的日志信息(sql server log or sql server and Windows log)方法三:去安装路径下去找你的log文件,我的默认实例路径如下driver:\SQL Server 2008 R2\MSSQL10_50.MSSQLSERVER\MSSQL\Log\ERRORLOG
‘捌’ sql关系代数表达式改为语法树减法怎么写
首先先介绍概念,对于查询处理,一般分为三个步骤:
对SQL语句进行语法分析,即将查询语句转换成按照某种有用方式表示查询语句结构的语法树
把语法分析树转换成关系代数表达式树(或某种类似标记),一般称之为逻辑查询计划
逻辑查询计划必须转换成物理查询计划,物理查询计划不仅指明了要执行的操作,而且也找出了这些操作执行的顺序、执行每步所用的算法,获得所存储数据的方式以及数据从一个操作传递给另一个操作的方式,除此之外,还必须估计每个可能选项的预计代价。
以下是详细的步骤。
查询的编译
1:语法分析与预处理
语法分析与语法分析树
原子
语法类
SQL简单子集的语法(语法分析)
查询
‘玖’ 如何获取SQL2005下的SQL语句的语义分析
我想获取一段sql语句在 mssql2005下解析成的语句,
主要是想获取这个sql所用到的所有的表的名字。(ps:复杂的sql语句的)
请高手帮忙 在线等~
我的意思是要从用户输入的sql语句中提取该语句中所用的表
或者是:
sql 执行的步骤
1. 解析器
第 1 阶段是解析器阶段,它将 SQL 文本转换成语法树。这个阶段不查找系统目录中的任何信息,不访问数据库。
2. 语义分析
第 2 阶段分析由解析器创建的语法树,并产生用于查询的查询控制块和表达式树。要构建这些内部数据结构,它执行以下操作:
验证对象
解析 UDR
如果可能的话,消除常量
验证对象
第 2 阶段访问数据库中不同的系统目录,以验证查询所引用的所有数据库对象(诸如表、列、视图、类型、UDR 等等)是否都存在。它在数据库中找到这些对象的标识,然后创建查询控制块和表达式树。
我要的就是验证对象步骤里的表的信息