阅读更多

20顶
0踩

数据库

转载新闻 Java开发者写SQL时常犯的10个错误

2015-03-10 11:22 by 副主编 mengyidan1988 评论(7) 有11405人浏览
我十分惊讶的发现,我最近的一篇文章——《Java开发者写SQL时常犯的10个错误》——最近在我的博客和我的合作伙伴DZone上非常的受欢迎。(这篇博客)的流行程度说明了几件事:
  • SQL在专业的Java开发中多么重要;
  • 基本的SQL知识被忘掉(的情况)普遍存在;
  • 通过embracing SQL,你就能了解像 jOOQ或MyBatis这样的以SQL为中心的库正好反应了市场的需要。 令人惊喜的是有用户提到了我博客上贴的一篇“SLICK’s mailing list”,SLICK是Scala中的一个不以SQL为中心的数据库访问库,像LINQ(还有LINQ-to-SQL),它侧重语言整合,而不是SQL语句的产生。

无论如何,我之前仓促列出的常见错误还没列完。因此我为你另外准备了10个没那么常见的,但Java开发者在写SQL语句时同样爱犯的错误。
1、不用PreparedStatements
有意思的是,在JDBC出现了许多年后的今天,这个错误依然出现在博客、论坛和邮件列表中,即便要记住和理解它是一件很简单的事。开发者不使用PreparedStatements的原因可能有如下几个:
  • 他们对PreparedStatements不了解
  • 他们认为使用PreparedStatements太慢了
  • 他们认为写PreparedStatements太费力

来吧,我们来破除上面的谣言。96%的案例中,用PreparedStatement比静态声明语句更好。为什么呢?就是下面这些简单的原因:
  • 使用内联绑定值(inlining bind values)可以从源头上避免糟糕的语句引起语法错误。
  • 使用内联绑定值可以避免糟糕的语句引起的SQL注入漏洞。
  • 当插入更多“复杂的”数据类型(比如时间戳、二进制数据等等)时,可以避免边缘现象(edge-cases)。
  • 你若保持PreparedStatements的连接开启状态而不马上关闭,只要重新绑定新值就可以进行复用。
  • 你可以在更多复杂的数据库里使用adaptive cursor sharing——自适应游标共享(Oracle的说法)。这可以帮你在每次新设定绑定值时阻止SQL语句硬解析。

(译者注:硬解析的弊端。硬解析即整个SQL语句的执行需要完完全全的解析,生成执行计划。而硬解析,生成执行计划需要耗用CPU资源,以及SGA资源。在此不得不提的是对库缓存中 闩的使用。闩是锁的细化,可以理解为是一种轻量级的串行化设备。当进程申请到闩后,则这些闩用于保护共享内存的数在同一时刻不会被两个以上的进程修改。在 硬解析时,需要申请闩的使用,而闩的数量在有限的情况下需要等待。大量的闩的使用由此造成需要使用闩的进程排队越频繁,性能则逾低下)

某些特殊情况下你需要对值进行内联绑定,这是为了给基于成本的性能优化器提示该查询将要涉及的数据集。典型的情况是用“常量”判断:
  • DELETED = 1
  • STATUS = 42

而不应该用一个“变量”判断:
  • FIRST_NAME LIKE “Jon%”
  • AMOUNT > 19.95

要注意的是,现代数据库已经实现了绑定数据窥探(bind-variable peeking)。因此,默认情况下,你也可以为你所有的查询参数使用绑定值。在你写嵌入的JPQL或嵌入的SQL时,用JPA CriteriaQuery或者jOOQ这类高层次的API可以很容易也很清晰的帮你生成PreparedStatements语句并绑定值。
更多的背景资料:

解决方案:

默认情况下,总是使用PreparedStatements来代替静态声明语句,而永远不要在你的SQL语句嵌入内联绑定值。

2、返回太多列

这个错误发生的非常频繁,它不光会影响你的数据库执行计划,也会对你的Java应用造成不好的影响。让我们先看看对后者的影响:

对Java程序的不良影响:

如 果你为了满足不同DAO层之间的数据复用而select *或者默认的50个列,这样将会有大量的数据从数据库读入到JDBC结果集中,即使你不从结果集读取数据,它也被传递到了线路上并被JDBC驱动器加载到 了内存中。如果你知道你只需要2-3列数据的话,这就造成了严重的IO和内存的浪费。

这个(问题的严重性)都是显而易见的,要小心……

对数据库执行计划的不良影响:

这 些影响事实上可能比对Java应用的影响还要严重。当复杂的数据库要针对你的查询请求计算出最佳执行计划时,它会进行大量的SQL转换(SQL transformation )。还好,请求中的一部分可以被略去,因为它们对SQL连映射或过滤条件起不了什么作用。我最近写了一篇博客来讲述这个问题:元数据模式会对Oracle查询转换产生怎样的影响

现在,给你展示一个错误的例子。想一想有两个视图的复杂查询:
SELECT *
FROM  customer_view c
JOIN  order_view o
ON  c.cust_id = o.cust_id

每个关联了上述关联表引用的视图也可能再次关联其他表的数据,像 CUSTOMER_ADDRESS、ORDER_HISTORY、ORDER_SETTLEMENT等等。进行select * 映射时,你的数据库除了把所有连接表都加载进来以外别无选择,实际上,你唯一感兴趣的数据可能只有这些:
SELECT c.first_name, c.last_name, o.amount
FROM  customer_view c
JOIN  order_view o
ON  c.cust_id = o.cust_id

一个好的数据库会在转换你的SQL语句时自动移除那些不需要的连接,这样数据库就只需要较少的IO和内存消耗。

解决方案:

永远不要用select *(这样的查询)。也不要在执行不同请求时复用相同的映射。尽量尝试减少映射到你所真正需要的数据。

需要注意的是,想在对象-关系映射(ORMs)上达成这个目标有些难。
3、把JOIN当做了SELECT的子句

对于性能或SQL语句的正确性来说,这不算错。但是不管如何,SQL开发者应该意识到JOIN子句不是SELECT语句的一部分。SQL standard 1992定义了表引用:
6.3 <table reference>
 
<table reference> ::=
<table name> [ [ AS ] <correlation name>
[ <left paren> <derived column list> <right paren> ] ]
| <derived table> [ AS ] <correlation name>
[ <left paren> <derived column list> <right paren> ]
| <joined table>
 
7.4 <from clause>
 
<from clause> ::=
FROM <table reference> [ { <comma> <table reference> }... ]
 
7.5 <joined table>
 
<joined table> ::=
<cross join>
| <qualified join>
| <left paren> <joined table> <right paren>
 
<cross join> ::=
<table reference> CROSS JOIN <table reference>
 
<qualified join> ::=
<table reference> [ NATURAL ] [ <join type> ] JOIN
<table reference> [ <join specification> ]

关联数据库是以表为中心的。许多的操作的某方面都是执行在物理表、连接表或派生表上的。为了有效的写出SQL语句,理解SELECT … FROM子句是以“,”分割表引用是非常重要的。

基于表引用(table references)的复杂性,一些数据库也接受其它类型的复杂的表引用(table references),像INSERT、UPDATE、DELETE、MERGE。看看Oracle实例手册,里面解释了如何创建可更新的视图。

解决方案:

一定要考虑到,一般说来,FROM子句也是一个表引用(table references)。如果你写了JOIN子句,要考虑这个JOIN子句是这个复杂的表引用的一部分:
SELECT c.first_name, c.last_name, o.amount
FROMcustomer_view c
JOIN order_view o
ON c.cust_id = o.cust_id

4、使用ANSI 92标准之前连接语法

我 们已经说清了表引用是怎么工作的(看上一节),因此我们应该达成共识,不论花费什么代价,都应该避免使用ANSI 92标准之前的语法。就执行计划而言,使用JOIN…ON子句或者WHERE子句来作连接谓语没有什么不同。但从可读性和可维护性的角度看,在过滤条 件判断和连接判断中用WHERE子句会陷入不可自拔的泥沼,看看这个简单的例子:
SELECT c.first_name, c.last_name, o.amount
FROM  customer_view c,
order_view o
WHERE  o.amount > 100
AND    c.cust_id = o.cust_id
AND    c.language = 'en'

你能找到join谓词么?如果我们加入数十张表呢?当你使用外连接专有语法的时候会变得更糟,就像Oracle的(+)语法里讲的一样。

解决方案:

一定要用ANSI 92标准的JOIN语句。不要把JOIN谓词放到WHERE子句中。用ANSI 92标准之前的JOIN语法没有半点好处。
5、使用LIKE判定时忘了ESCAPE

SQL standard 1992指出like判定应该如下:
8.5 <like predicate>
 
<like predicate> ::=
<match value> [ NOT ] LIKE <pattern>
[ ESCAPE <escape character> ]

当允许用户对你的SQL查询进行参数输入时,就应该使用ESCAPE关键字。尽管数据中含有百分号(%)的情况很罕见,但下划线(_)还是很常见的:
SELECT *
FROM  t
WHERE  t.x LIKE 'some!_prefix%' ESCAPE '!'

解决方案:

使用LIKE判定时,也要使用合适的ESCAPE

6、认为 NOT (A IN (X, Y)) 和 IN (X, Y) 的布尔值相反

对于NULLs,这是一个举足轻重的细节!让我们看看 A IN (X, Y) 真正意思吧:
A IN (X, Y)
is the same as    A = ANY (X, Y)
is the same as    A = X OR A = Y

When at the same time, NOT (A IN (X, Y)) really means:
NOT (A IN (X, Y))
is the same as    A NOT IN (X, Y)
is the same as    A != ANY (X, Y)
is the same as    A != X AND A != Y

看起来和之前说的布尔值相反一样?其实不是。如果X或Y中任何一个为NULL,NOT IN 条件产生的结果将是UNKNOWN,但是IN条件可能依然会返回一个布尔值。

或者换种说话,当 A IN (X, Y) 结果为TRUE或FALSE时,NOT(A IN (X, Y)) 结果为依然UNKNOWN而不是FALSE或TRUE。注意了,如果IN条件的右边是一个子查询,结果依旧。

不信?你自己看SQL Fiddle 去。它说了如下查询给不出结果:
SELECT 1
WHERE    1 IN (NULL)
UNION ALL
SELECT 2
WHERE NOT(1 IN (NULL))

更多细节可以参考我的上一篇博客,上面写了在同区域内不兼容的一些SQL方言。

解决方案:

当涉及到可为NULL的列时,注意NOT IN条件。
7、认为NOT (A IS NULL)和A IS NOT NULL是一样的

没错,我们记得处理NULL值的时候,SQL实现了三值逻辑。这就是我们能用NULL条件来检测NULL值的原因。对么?没错。

但在NULL条件容易遗漏的情况下。要意识到下面这两个条件仅仅在行值表达式(row value expressions)为1的时候才相等:

NOT (A IS NULL)
is not the same as A IS NOT NULL

如果A是一个大于1的行值表达式(row value expressions),正确的表将按照如下方式转换:

  • 如果A的所有值为NUll,A IS NULL为TRUE
  • 如果A的所有值为NUll,NOT(A IS NULL) 为FALSE
  • 如果A的所有值都不是NUll,A IS NOT NULL 为TRUE
  • 如果A的所有值都不是NUll,NOT(A IS NOT NULL)  为FALSE

在我的上一篇博客可以了解到更多细节。
解决方案:

当使用行值表达式(row value expressions)时,要注意NULL条件不一定能达到预期的效果。

8、不用行值表达式

行值表达式是SQL一个很棒的特性。SQL是一个以表格为中心的语言,表格又是以行为中心。通过创建能在同等级或行类型进行比较的点对点行模型,行值表达式让你能更容易的描述复杂的判定条件。一个简单的例子是,同时请求客户的姓名
SELECT c.address
FROM  customer c,
WHERE (c.first_name, c.last_name) = (?, ?)

可以看出,就将每行的谓词左边和与之对应的右边比较这个语法而言,行值表达式的语法更加简洁。特别是在有许多独立条件通过AND连接的时候就特别有效。行值表达式允许你将相互联系的条件放在一起。对于有外键的JOIN表达式来说,它更有用:
SELECT c.first_name, c.last_name, a.street
FROM  customer c
JOIN  address a
ON  (c.id, c.tenant_id) = (a.id, a.tenant_id)

不幸的是,并不是所有数据库都支持行值表达式。但SQL标准已经在1992对行值表达式进行了定义,如果你使用他们,像Oracle或Postgres这些的复杂数据库可以使用它们计算出更好的执行计划。在Use The Index, Luke这个页面上有解析。

解决方案:

不管干什么都可以使用行值表达式。它们会让你的SQL语句更加简洁高效。

9、不定义足够的限制条件(constraints)

我又要再次引用Tom Kyte 和 Use The Index, Luke 了。对你的元数据使用限制条件不能更赞了。首先,限制条件可以帮你防止数据质变,光这一点就很有用。但对我来说更重要的是,限制条件可以帮助数据库进行SQL语句转换,数据库可以决定。
  • 哪些值是等价的
  • 哪些子句是冗余的
  • 哪些子句是无效的(例如,会返回空值的语句)

有些开发者可能认为限制条件会导致(数据库)变慢。但相反,除非你插入大量的数据,对于大型操作是你可以禁用限制条件,或用一个无限制条件的临时“载入表”,线下再把数据转移到真实的表中。
解决方案:

尽可能定义足够多的限制条件(constraints)。它们将帮你更好的执行数据库请求。

10、认为50ms是一个快的查询速度

NoSQL的炒作依然在继续,许多公司认为它们像Twitter或Facebook一样需要更快、扩展性更好的解决方案,想脱离ACID和关系模型横向扩展。有些可能会成功(比如Twitter或Facebook),而其他的也许会走入误区:
看这篇文章:https://twitter.com/codinghorror/status/347070841059692545

对于那些仍被迫(或坚持)使用关系型数据 库的公司,请不要自欺欺人的认为:“现在的关系型数据库很慢,其实它们是被天花乱坠的宣传弄快的”。实际上,它们真的很快,解析20Kb查询文档,计算 2000行执行计划,如此庞大的执行,所需时间小于1ms,如果你和数据管理员(DBA)继续优化调整数据库,就能得到最大限度的运行。

它们会变慢的原因有两种:一是你的应用滥用流行的ORM;二是ORM无法针对你复杂的查询逻辑产生快的SQL语句。遇到这种情况,你就要考虑选择像 JDBC、jOOQ 或MyBatis这样的更贴近SQL核心,能更好的控制你的SQL语句的API。

因此,不要认为查询速度50ms是很快或者可以接受的。完全不是!如果你程序运行时间是这样的,请检查你的执行计划。这种潜在危险可能会在你执行更复杂的上下文或数据中爆发。
总结

SQL很有趣,同时在各种各样的方面也很微妙。正如我的关于10个错误的博客所展示的。跋山涉水也要掌握SQL是一件值得做的事。数据是你最有价值的资产。带着尊敬的心态对待你的数据才能写出更好的SQL语句。

本文由 ImportNew - zer0Black 翻译自 jooq
来自: ImportNew
20
0
评论 共 7 条 请登录后发表评论
7 楼 随意而生 2015-03-13 09:43
还是喜欢最原始的jdbc,像springjdbc那样加一层薄薄的封装也不错。
6 楼 ppjava2009 2015-03-12 18:23
这跟java有啥关系,一些非常的牵强,如“不用PreparedStatements”,怎能算是mistake?
5 楼 bellyoung 2015-03-11 13:03
确实很多东西可以在实际中用到。
4 楼 sonicwangyue 2015-03-11 10:18
有些地方没看懂。。谢谢
3 楼 netkiller.github.com 2015-03-10 18:06
数据库技术在进步,很多禁忌可能在新版本上不试用。
2 楼 white_crucifix 2015-03-10 14:17
sql是个让人又爱又恨的东西,sql的设计确实反人类,但它的确能解决很多现实问题
1 楼 k10509806 2015-03-10 13:36
实际应用中,很多都会出现所谓的“错误”,其实都是要用到的

发表评论

您还没有登录,请您登录后再发表评论

相关推荐

  • H264视频压缩编码标准

    该文档介绍了H.264/AVC编解码器及其结构,还有帧内预测、帧间预测和变换与量化,对初学者有很大的帮助

  • H264基本知识

    压缩比为1%

  • H264压缩比和编码码率

    在格式为YUV420的情况下,分辨率为1280x1024,帧率为60,每秒传输1280x1024x60X1.5x8 = 943,718,400 bit = 943.7184 Mbps,因此至少需要944Mb/s。这时设置H264的编码码率为9440kpbs,此时H264的压缩率为100:1。若是300:1则倒推设置码率为3146kbps,压缩比为80:1就是倒推码率11800。实际上264的压缩率没有这么高,这里只是进行举例介绍。265压缩率:500倍,实际300倍。264压缩率:250倍。

  • H.264压缩编码算法介绍

    在这里我总结了许多博客专家对H.264压缩编码算法的理解,得出了我个人的一些见解。现在本人正在研究Android视频直播这一方面的知识,只是设备是定制的Android设备,不是很正规的Android系统。所以这一套的算法放在Android上运行很流畅也不见得可以在定制的设备上完美的运行。无奈之下只得从头开始分析源代码,坚持将自己的学习过程记录下来。一是给自己每天的学习做一个记录,二是通过分享自己的学

  • H264编码原理

    一、H264压缩码率与GOP 1. H264压缩比: 条件: YUV格式为YUV420 分辨率为640x480 帧率为15 未压缩的YUV码流为: 640*480*1.5*15*8 = 52.7343mbps H264建议码流: 500kbps 结果: 约1/100 码流参考值: 建议码流,不是科学计算的,而是各个厂家经过实践的经验值。可以参考如下网站(声网) https://docs.agora.io/cn 在上述网站如下目录:视频通话==&gt; 进阶功能==&gt;视频管理==&gt;设置视频属性

  • H264编码原理(H264压缩比与GOP)

    H264压缩比 条件: 1、YUV格式为YUV420。 乘1.5倍,rgb是3倍 2、分辨率为640x480 3、帧率为15 原视频未压缩需要6404801.5158 = 55296000(bit),约55M (一秒). H264建议码流为500kps 结果: 约1/100 码流参考值 常用的h264建议码流都并非科学计算得出的,而是各个厂家经过大量实践得出的经验值。 常用的查询网址: https://docs.agora.io/cn 这是声网总结的经验值,声网在音视频领域是比较权

  • H.264压缩算法详解

    H.264压缩算法详解    H.264是一种视频高压缩技术,全称是MPEG-4 AVC,用中文说是“活动图像专家组-4的高等视频编码”,或称为MPEG-4 Part10。它是由国际电信标准化部门ITU-T和规定MPEG的国际标准化组织ISO/国际电工协会IEC共同制订的一种活动图像编码方式的国际标准格式,这是我们叫惯了的MPEG中的一种,那为什么叫H.264呢?    原来国际电信标准化

  • 编解码格式 -- H264

    H264MPEG编解码格式历史对应关系H264编解码原理视频数据能被大量压缩的原因H264视频编码常见名词帧(frame)场(field)片(slice)宏块(macro block)序列(GOP)序列参数集 SPS(Sequence Parameter Set )图像参数集 PPS(Picture Parameter Set )参考帧H264数据层级的关系SPS、PPS和视频数据间的关系H264的分层结构H264的主要目标H264的规格(profile)H264的等级(level)帧间(intra)预测和

  • H264视频压缩算法

    H264视频压缩算法现在无疑是所有视频压缩技术中使用最广泛,最流行的。随着 x264/openh264以及ffmpeg等开源库的推出, 大多数使用者无需再对H264的细节做过多的研究,这大降低了人们使用H264的成本。 但为了用好H264,我们还是要对H264的基本原理弄清楚才行。今天我们就来看看H264的基本原理。 H264概述 H264压缩技术主要采用了以下几种方法对视频...

  • 音视频学习笔记001:初识H.264

    **H.264**是新一代数字**视频压缩格式**,是一种**视频编码标准**; 由**国际标准化组织(ISO)**和**国际电信联盟(ITU)**共同提出的继**MPEG4**之后的新一代数字**视频压缩格式**,它不具体规定一个编码器的如何实现,是一种**视频编码标准**。H.264着重强调更高的编码压缩率和传输可靠性;

  • 视频编码 H.264 vs H.265,有什么不同(内容比较全,建议收藏)

    H.264和H.265:它们是什么?哪一个更好?在相机录制格式中,我们经常会遇到H.264和H.265。但它们到底是什么意思?一些人认为H.264更通用、更优越。其他人则声称,与H.264相比,H.265提供了更先进的编码,允许更长的视频、更小的存储要求和更好的图像质量。到目前为止,您可能对H.264与H.265有各种疑问。在这篇文章中,我们的目的是阐明这两种视频编码格式之间的差异,所以让我们深入...

  • 系统化学习 H264视频编码(03)数据压缩流程及相关概念

    说明:我们参考黄金圈学习法(什么是黄金圈法则?->模型 黄金圈法则,本文使用:why-what)来学习音H264视频编码。本系列文章侧重于理解视频编码的知识体系和实践方法,理论方面会更多地讲清楚 音视频中概念的起源以及各个概念的联系。知其然,知其所以然。同时更强调知识系统的建立。针对本文,我们主要讲研究 H.264数据压缩的流程及其相关概念。H.264数据压缩的目的只有一个,压缩压缩再压缩,减少视频数据大小的同时尽可能地保证图像质量。

  • 【数据压缩】H.264编码

    H.264,同时也是MPEG-4第十部分,是由ITU-T视频编码专家组(VCEG)和ISO/IEC动态图像专家组(MPEG)联合组成的联合视频组(JVT,Joint Video Team)提出的高度压缩数字视频编解码器标准。

  • 视频编码:H.264编码

    本文参考毕厚杰老师《新一代视频压缩编码标准-----H.264/AVC》一书以及雷霄骅博客《视音频编解码技术零基础学习方法》整理。 1.概念部分: H.264编码: 视频编解码技术有两套标准,国际电联(ITU-T)的标准H.261、H.263、H.263+等;还有ISO 的MPEG标准Mpeg1、Mpeg2、Mpeg4等等。H.264/AVC(又被称为MPEG-4 Part 10)是两大组织集合...

  • H264基础知识入门

    I和IDR帧都使用帧内预测,在编码解码中为了方便,首个I帧要和其他I帧区别开,把第一个I帧叫IDR,这样方便控制编码和解码流程。IDR帧必须是一个I帧,但是I帧不一定是IDR帧,这个帧出现的时候,是告诉解码器,可以清除掉所有的参考帧,这是一个全新的序列,新的GOP已经开始。I帧有被跨帧参考的可能,IDR不会。I帧是所有数据帧最关键的帧,如果缺少了I帧,后面的数据帧将无法使用。** 编码后数据,根据I帧P帧B帧的特性,在解码的过程是按I帧、P帧和B帧进行解码,文件播放还是按I帧、B帧和P帧顺序播放。

  • H264基本原理

    H264视频压缩算法现在无疑是所有视频压缩技术中使用最广泛,最流行的。随着 x264/openh264以及ffmpeg等开源库的推出,大多数使用者无需再对H264的细节做过多的研究,这大降低了人们使用H264的成本。但为了用好H264,我们还是要对H264的基本原理弄清楚才行。今天我们就来看看H264的基本原理。

  • java 处理 barCode(条形码)

    生成条形码:<br />1.下载压缩包barcode4j-2.0alpha2-bin.zip和barcode4j-2.0alpha2-src.zip。<br />2、解压barcode4j-2.0alpha2-bin.zip这个包,在build目录下有barcode4j.jar,在lib目录下有avalon- framework-4.2.0.jar, 将barcode4j.jar和avalon-framework-4.2.0.jar添加到项目的lib中,刷新工程,然后在项目配置中将这两个jar 包添加到cl

  • 视频压缩标准发展历史(一)

    视频压缩标准发展历史 数字视频技术广泛应用于通信、计算机、广播电视等领域,带来了会议电视、可视电话及数字电视、媒体存储等一系列应用,促使了许多视频编码标准的产生。ITU-T与ISO/IEC是制定视频编码标准的两大组织,ITU-T的标准包括H.261、H.263、H.264,主要应用于实时视频通信领域,如会议电视;MPEG系列标准是由ISO/IEC制定的,主要应用于视频存储(DVD)、广播电视、因

  • 【H.264/AVC视频编解码技术详解】三. H.264简介

    《H.264/AVC视频编解码技术详解》视频教程已经在“CSDN学院”上线,视频中详述了H.264的背景、标准协议和实现,并通过一个实战工程的形式对H.264的标准进行解析和实现,欢迎观看!“纸上得来终觉浅,绝知此事要躬行”,只有自己按照标准文档以代码的形式操作一遍,才能对视频压缩编码标准的思想和方法有足够深刻的理解和体会!链接地址:H.264/AVC视频编解码技术详解(部分视频在审核中)本节视频免

  • 解析JM代码比较理解H264语法元素解码ue(v),se(v),u(n)

    ue(v):无符号整数指数哥伦布码编码的语法元素,左位在先。 se(v):有符号整数指数哥伦布码编码的语法元素,左位在先。 u(n):n位无符号整数。在语法表中,如果n是‘v’,其比特数由其它语法元素值确定。解析过程由函 数read_bits(n)的返回值规定,该返回值用最高有效位在前的二进制表示。   //! Syntaxelement 。an important data struc...

Global site tag (gtag.js) - Google Analytics