哥最近使用MSSQL,用出火来了,不仅仅是因为不熟悉,而且是因为MSSQL那些自以为是、闭门造车、落后过时的设计!
所以要开此贴,把这些弱智之处记录下来!1、select * from tablexxx; 这样没有order by 的sql 默认按照主码排序问题。
首先我没有让你排序,你给我排序干嘛?你不知道排序数据会造成效率严重下降吗?
就算你是按照聚簇索引输出的而不是索引排序,我让你建聚簇索引了吗?你不知道聚簇索引在插入和更新数据时会有效率问题吗?2、数据字典中大量使用数字而不是易读的字符串代表名称、类型等问题。
这就是为什么google上很多syscolumns表中各个列代表什么意思的文章出现的原因。难道用对象名、数据类型名等等这些字符串不行吗?你以为用数字ID就比字符串效率低了?3、一次性返回所有行的问题。
只要数据量稍微多点,sqlserver都会很慢,为什么?因为它会把所有数据都一次性查出来?有必要吗?你不知道首先快速的返还出100行来,等我请求第101行的时候你再返回200行吗?4、 Convert等这样又像函数又像语句的不知道叫啥好的东西的问题。
你要是定义成Convert(‘varchar’, column1..)这样我还可以理解,但是你竟然定义成Convert(varchar, column1..),那我问你varchar是什么啊? 是字符串,那Convert就是一个函数,应该加上单引号, 如果是类型,那Convert就应该是语句,格式就应该是Convert varchar from column1等等这样的格式,而不是类似一个函数5、未完待续

解决方案 »

  1.   

    跟上次那个“侮辱智商”的帖子异曲同工啊:
    http://topic.csdn.net/u/20101212/07/cfd81a8f-b6e6-4af2-b107-654cd29f955d.html
      

  2.   

    1、select * from tablexxx; 这样没有order by 的sql 默认按照主码排序问题。
    首先我没有让你排序,你给我排序干嘛?你不知道排序数据会造成效率严重下降吗?
    就算你是按照聚簇索引输出的而不是索引排序,我让你建聚簇索引了吗?你不知道聚簇索引在插入和更新数据时会有效率问题吗?
    ====
    不指定ORDER BY,查询结果会按照数据的物理顺序返回,即以最直接方便的顺序返回。不会额外排序。
    表上如果有聚集索引,那一定是你让它建的。别赖别人。
    SQL Server开发团队在这点上比LZ想象得要聪明得多。2、数据字典中大量使用数字而不是易读的字符串代表名称、类型等问题。
    这就是为什么google上很多syscolumns表中各个列代表什么意思的文章出现的原因。难道用对象名、数据类型名等等这些字符串不行吗?你以为用数字ID就比字符串效率低了?
    ====
    表示元数据的系统视图太符合范式了,把类型的ID和类型的Name分开了。
    确实应该再加一层更Human-readable的视图。3、一次性返回所有行的问题。
    只要数据量稍微多点,sqlserver都会很慢,为什么?因为它会把所有数据都一次性查出来?有必要吗?你不知道首先快速的返还出100行来,等我请求第101行的时候你再返回200行吗?
    ====
    SELECT * FROM table,就是要查询所有记录,如果只返回一部分,那是bug。
    很多工具都假定程序员是聪明的,知道自己要做什么。比如Linux的命令行都是直接返回执行结果,而不像Windows的CMD命令,常常自以为是地自动分页。
    不过既然在SSMS中查询数据,通常只是为了查看示例而不是所有数据,那SSMS在这一点上的确应该遵守微软的传统,加一个提醒:“数据量很大,可能比较慢”,等等之类。但众口难调,这样的设计也一定会被骂。4、 Convert等这样又像函数又像语句的不知道叫啥好的东西的问题。
    你要是定义成Convert(‘varchar’, column1..)这样我还可以理解,但是你竟然定义成Convert(varchar, column1..),那我问你varchar是什么啊? 是字符串,那Convert就是一个函数,应该加上单引号, 如果是类型,那Convert就应该是语句,格式就应该是Convert varchar from column1等等这样的格式,而不是类似一个函数
    ====
    LZ没听说过枚举类型和常量吗?
    类型转换的SQL标准写法:CAST(column AS varchar),CONVERT是SQL Server加的,用来处理不同style的转换问题。
    LZ愿意的话,可以设计个更好用的语法格式。
      

  3.   

    1、楼上的哥们,我先插入了一个ID为10的行,然后又插入了一个ID为1的行,结果我不用order by 直接查询时,它竟然返回ID为1的行在id为10的行前面,怎么解释?不管是自动按照主码排序,还是自动按照主码存放了数据,都会造成严重的性能的降低,都是自作多情和多此一举。难道让ID为1的在id为10的后面输出不行吗?2、你说把ID和Name分开,那ID难道就一定得是数字吗?2、你说一次性不返回所有行是bug,我说不返回所有的行吗?我说不必一次性返回,而是应该分批返回。好比让你吃饭,你一次把一辈子的饭都吃了,肯定会撑死,但是饿的时候吃一顿,慢慢的把所有的饭都吃了才是最合适的。4、你说是枚举类型,那我问你建表是后面的那个类型可以是枚举类型和常量吗?就算是枚举类型,那也应该换一个别的样子,而不是和建表时的类型一样。
      

  4.   

    1、select * from tablexxx; 这样没有order by 的sql 默认按照主码排序问题。
    首先我没有让你排序,你给我排序干嘛?你不知道排序数据会造成效率严重下降吗?
    就算你是按照聚簇索引输出的而不是索引排序,我让你建聚簇索引了吗?你不知道聚簇索引在插入和更新数据时会有效率问题吗?如果你没建聚集索引,并且没有做任何修正数据库空间的结构,数据会以类似于链表的形式存储,不加ORDER BY时,不会有排序的行为
    IF OBJECT_ID('TB') IS NOT NULL DROP TABLE TB
    GO
    CREATE TABLE TB(COL1 INT)
    INSERT INTO TB 
    SELECT 10
    GO
    INSERT INTO TB
    SELECT 1
    GO
    SELECT * FROM TB
    /*
    COL1
    -----------
    10
    1
    */2、数据字典中大量使用数字而不是易读的字符串代表名称、类型等问题。
    这就是为什么google上很多syscolumns表中各个列代表什么意思的文章出现的原因。难道用对象名、数据类型名等等这些字符串不行吗?你以为用数字ID就比字符串效率低了?
    对象ID本来就是内部使用的,所以可读性并不重要,当我们需要根据对象的名称查询时,一般会通过OBJECT_ID函数与系统表进行比较,或者用OBJECT_NAME把对象ID转为对象名称。比如下面的语句返回TB表的所有列名
    /*
    IF OBJECT_ID('TB') IS NOT NULL DROP TABLE TB
    GO
    CREATE TABLE TB(COL1 INT,COL2 INT)
    SELECT NAME FROM SYS.COLUMNS WHERE OBJECT_ID=OBJECT_ID('TB')
    /*
    NAME
    --------------------------------------------------------------------------------------------------------------------------------
    COL1
    COL2
    */
    */3、一次性返回所有行的问题。
    只要数据量稍微多点,sqlserver都会很慢,为什么?因为它会把所有数据都一次性查出来?有必要吗?你不知道首先快速的返还出100行来,等我请求第101行的时候你再返回200行吗?你要求的这个功能我没听说在别的数据库上能实现,这种需求更像是由客户端对语句进行二次解析并在数据库层面进行分页处理。在数据库设计原理里好像也没有类似的设计。4、 Convert等这样又像函数又像语句的不知道叫啥好的东西的问题。
    你要是定义成Convert(‘varchar’, column1..)这样我还可以理解,但是你竟然定义成Convert(varchar, column1..),那我问你varchar是什么啊? 是字符串,那Convert就是一个函数,应该加上单引号, 如果是类型,那Convert就应该是语句,格式就应该是Convert varchar from column1等等这样的格式,而不是类似一个函数varchar在这里应该算是枚举值,不是字符串,也不是类型5、未完待续枪手如果觉得枪不好,可以换枪,因为别人能用这种枪打死人你不行,说明不是枪的问题。
      

  5.   

    2、所有对象在它的系统表里由统一的记录维护着,id只是记录的自动递增id而已3、这个应该是应用要做好的事情,数据库等准备好了直接返回是对的
      

  6.   

    1、楼上的哥们,我先插入了一个ID为10的行,然后又插入了一个ID为1的行,结果我不用order by 直接查询时,它竟然返回ID为1的行在id为10的行前面,怎么解释?不管是自动按照主码排序,还是自动按照主码存放了数据,都会造成严重的性能的降低,都是自作多情和多此一举。难道让ID为1的在id为10的后面输出不行吗?对于性能的评价应该建立在实际的测试环境和数据量的情况下,而不是通过在自己的机器上插入两条数据就能推导出数据库的存储原理。2、你说把ID和Name分开,那ID难道就一定得是数字吗?为什么不能是数字2、你说一次性不返回所有行是bug,我说不返回所有的行吗?我说不必一次性返回,而是应该分批返回。好比让你吃饭,你一次把一辈子的饭都吃了,肯定会撑死,但是饿的时候吃一顿,慢慢的把所有的饭都吃了才是最合适的。如果你用大数据量查询的话你会发现,是分批返回的,机器卡可能是你机器问题,在我们的客户端上,几百万数据的表全部返回大概用2到5秒,前1秒之内就会有第一批数据返回。4、你说是枚举类型,那我问你建表是后面的那个类型可以是枚举类型和常量吗?就算是枚举类型,那也应该换一个别的样子,而不是和建表时的类型一样。枚举值和字段类型一样估计是为了方便记忆,至少我就不用每次用的时候现去查帮助看类型对应的枚举值是什么。另外建表时指定的类型我认为也应该算是一种枚举值。
      

  7.   


    1、你这个测试建立主码了吗?2、内部使用的Id难道不能是可读性更好的字符串吗?3、Oracle上就实现了,不行你拿个一千万行的oracle表,和1千万行的mssql表试试,oracle可以瞬间返回一屏数据,而mssql估计要挂了4、既然在同一个语言内,不应该存在完全相同的一个数据类型和一个枚举值。5、有人能用,那不一定就是好的。社会应该让对那些更好的公司和产品更好的发展才行。好的就该受到鼓励,不好的就该受到批判。
      

  8.   

    LZ的话让我想到了我们寝当年一直用卡宾的兄弟换成AK时的语气
      

  9.   

    这些倒不是大问题,最大的问题是:select出来结果的时候,没有自动加一个序号列foid
    如果有了它,分页就是很简单的事情了:
    select * from (
    select * from tb where ... order by ...  
    ) a where foid>10000 and foid<10020
    或者
    select top 20 skip 10000 * from tb where ... order by ...  
    2005后有了一个rank的扩展语法
      

  10.   

    1、楼上的哥们,我先插入了一个ID为10的行,然后又插入了一个ID为1的行,结果我不用order by 直接查询时,它竟然返回ID为1的行在id为10的行前面,怎么解释?不管是自动按照主码排序,还是自动按照主码存放了数据,都会造成严重的性能的降低,都是自作多情和多此一举。难道让ID为1的在id为10的后面输出不行吗?
    ====
    你确定ID字段上没有聚集索引?你确定这个聚集索引不是你建的?
    此外,LZ还是像很多初学者一样把主键和聚集索引混为一谈了。2、你说把ID和Name分开,那ID难道就一定得是数字吗?
    ====
    整数型的好处是空间小、容易自动生成;缺点是可读性不好,需要再做查询或调用函数解析。
    LZ可以考虑设计个更好的类型来表示ID。2、你说一次性不返回所有行是bug,我说不返回所有的行吗?我说不必一次性返回,而是应该分批返回。好比让你吃饭,你一次把一辈子的饭都吃了,肯定会撑死,但是饿的时候吃一顿,慢慢的把所有的饭都吃了才是最合适的。
    ====
    数据如何分批显示本来就不是数据库层需要考虑的问题。LZ乐意可以自己试试。4、你说是枚举类型,那我问你建表是后面的那个类型可以是枚举类型和常量吗?就算是枚举类型,那也应该换一个别的样子,而不是和建表时的类型一样。
    ====
    可以把数据类型理解成一个系统内置的枚举值,不可修改和赋值。同一样事物,在不同地方当然要统一。建表时一种写法,类型转换时一种写法,那才叫纠结。
    之所以不是CONVERT('varchar',column)是因为SQL是静态类型,不允许出现下面的情况:
    DECLARE @datatype varchar(100)
    SET @datatype = 'varchar'
    SELECT CONVERT(@datatype,column) FROM table ...
    LZ如果觉得这是个限制,可以考虑自己实现一个DBMS,应该会比SQL Server卖得好。
      

  11.   

    1、你这个测试建立主码了吗?如果你说的是主键的话,请仔细查看帮助,当声明列为主键并没有显式声明主键索引为非聚集时,系统主键会默认为聚集索引,这时索引的叶子节点就是数据页,因为索引是排序的,所以不指定排序列就会按主键的顺序输出。如果你不想让主键是聚集的,可以在表定义时声明。2、内部使用的Id难道不能是可读性更好的字符串吗?为什么你的身份证号不是可读性更好的你的名字加一个GUID?3、Oracle上就实现了,不行你拿个一千万行的oracle表,和1千万行的mssql表试试,oracle可以瞬间返回一屏数据,而mssql估计要挂了见11楼4、既然在同一个语言内,不应该存在完全相同的一个数据类型和一个枚举值。这个实在是看不懂,也没听说过类似的说法,SORRY5、有人能用,那不一定就是好的。社会应该让对那些更好的公司和产品更好的发展才行。好的就该受到鼓励,不好的就该受到批判。按你的说法,汇编语言是最应该批判的,至少我学的时候就异常痛苦。
      

  12.   


    CREATE TABLE TB(
    ID int NOT NULL PRIMARY KEY NONCLUSTERED,
    COLName varchar(100) NOT NULL)
    GO
    INSERT INTO TB
    SELECT 10, 'ten'
    GO
    INSERT INTO TB
    SELECT 1, 'one'
    GO
    SELECT * FROM TB
    /*
    ID  COLName
    --- --------
    10  ten
    1   one
    */
      

  13.   


    所以LZ肯定是不知道非聚集索引在插入和更新时也会有效率问题。如果LZ知道一种不使用现有B+树索引的机制来实现主键的功能,那真是跨时代的发现啊。
      

  14.   

    引用技术内幕上的一段话:
    SQL SERVER的一个典型应用是大部分读者可能 都熟悉的纳斯达克指数系统。该系统在两台4个结点的DELL POWEREDGE 6850集群计算机上运行SQL SERVER2005,以支持它的市场数据分发系统(MDDS)。纳斯达克市场处理的每个交易日都会经过MDDS,开市时SQL SERVER2005每秒可处理5000次交易。
      

  15.   

    再次声明不是不支持LZ的批判精神,因为所有新技术的出现都是由于对现在技术的不满,如果没有不满,就不会有进步。
    但在遇到问题时,首先应该做的是检查自己有没有对要做的事情和使用的工具完全了解,或者想办法从文档和社区里得到帮助,抱怨解决不了任何问题。另外如果实在用着不爽就换回ORACLE好了,我就是用ORACLE的客户端用的不爽才改成MSSQL的。
      

  16.   


    这么牛啊?一个系统的数据库选择,仅仅因为你的客户端使用体验?
    当然,我也是非常不满oracle/db2这些的java写的又慢又非内存的客户端的。即使是mssql,2005的客户端居然比2000的慢!
      

  17.   

    oracle没有分批返回数据吧?楼主是不是把pl/sql工具和oracle混为一谈了?那个分页是那工具分页的,不是oracle本身分的吧?其实sql2005的sql server management studio也有类似的功能,它会在你拉动滚动条的时候逐步加载数据.但这不是数据库本身的功能吧.另外,当你用异步方式提取数据时,数据是可以一批一批返回的.
      

  18.   


    聚簇索引肯定就是和oracle里的索引排序表一样,指的是表里的数据也是按照索引的顺序存储的,否则就不会有一个表只有一个聚簇索引的限制了。这也说明,mssql对"聚簇索引"的命名方法不对,还是“索引排序表”更准确。
      

  19.   


    alter session set optimizer_mode='FIRST_ROWS_1000' 怎么解释?
      

  20.   


    一行数据包括主码和非主码,主码当然可以按照排序存储,而且因为主码大都是小数据块,所以效率可以忍受,但是其他的非主码数据呢,难道也要排序存储?MSSQL默认按照主码输出只可能有两个原因:
    1、默认在主码上建立了聚簇索引,造成整个表成了“索引排序表”,这种表在插入和更新数据时,行中的非主码数据也会按照聚簇索引的顺序存放在表的文件里,从而造成效率下降。
    2、MSSQL的执行计划走了主码索引,从而是数据输出按照主码排序。但是我们都知道,走索引并不一定是效率最高的,很多时候还不如全表扫面速度快,这说明,MSSQL的优化器设计过时和不够智能的。
    3、不可能有任何第三种可能,但是上面两种情况都证明MSSQL的设计过时。当然,还是微软自己说得对,微软仅仅是一家为中小企业提供服务的公司。
      

  21.   

    先不说技术。
    楼主可以试着做这件事情:两臂膀张开,然后以较快的速度把左右手的手指叉起来;再做一次;再做一次;如果有兴趣的话,再多几次,
    做了吗?
    你会发现你每次做的时候,都是某一只手的大拇指压着另一只手。
    那现在再几次,要求以前被压着的大拇指压着以前压着的大拇指。
    感觉怎样,不太习惯吧?
    再多做几次,
    有点习惯了吧?其实都是不太习惯造成了你的愤怒。
    我也不太习惯SQL Server里某些东西,比如有了char,又有nchar,像mysql那样指定内码不多好?
    后来发现Informix也有char与nchar,我相信总是有原因的。凡事,习惯了就好了!
      

  22.   

    微软的方向是大众化的,不是专业化的。在追求易用性上必然会损失性能。这是微软的成功之道!!牛人分析的,不是我啊!想想windows 和 dos 就知道了。
      

  23.   


    Index Organized Tables(索引排序表)是Oracle一家的叫法;Clustered Index(聚集索引,或译聚簇索引)是数据库领域通行的叫法,当然也是MSSQL采用的叫法。采用什么叫法主要要看交流对象,入乡随俗。在Oracle区自然叫索引排序表,在MSSQL区自然叫聚集索引,在数据库理论领域进行探讨也叫聚集索引。LZ敢于轻易说出“这也说明,mssql对"聚簇索引"的命名方法不对”,真是无知者无畏。(这里的“无知”只是对知识的描述,不是对人格的侮辱)在世界面前,人类都是无知的。关键是要知道自己知道什么以及自己不知道什么,然后保持虚怀若谷的态度。无知+自大是最可怕的。
      

  24.   

    如果这么说我觉得就没法沟通了,feilniu大大继续跟他扯吧,我撤退。
      

  25.   


    --SQL Server
    SET ROWCOUNT 1000
      

  26.   

    MSSQL默认按照主码输出只可能有两个原因:
    (这一步推理不严格。全表数据按主码顺序输出,并不能说明主码是聚集索引,也可能是非聚集覆盖索引。不过这点疏漏无碍。大体逻辑正确。)
    1、默认在主码上建立了聚簇索引,造成整个表成了“索引排序表”,这种表在插入和更新数据时,行中的非主码数据也会按照聚簇索引的顺序存放在表的文件里,从而造成效率下降。
    (MSSQL的主码的确是默认为聚集索引。聚集索引优在查询快捷,劣在更新消耗。这个要综合考量。数据按聚集索引顺序存储,可MSSQL并不是简单地把所有数据线性地摆放在磁盘里。事实证明MSSQL把主码默认为聚集索引的设计并不是什么错误的决定。)
    2、MSSQL的执行计划走了主码索引,从而是数据输出按照主码排序。但是我们都知道,走索引并不一定是效率最高的,很多时候还不如全表扫面速度快,(很多时候并不是总是,也不能说明就是这个时候)这说明,MSSQL的优化器设计过时和不够智能的。(所以最后的结论是武断和不负责任的)
    3、不可能有任何第三种可能,(基本正确)但是上面两种情况都证明MSSQL的设计过时。(结论武断)