发布新日志

  • MYSQL 上的coalesce用法

    2011-04-28 15:42:12

    coalesce(字段,0) 如果字段中返回为NULL 的时候返回0
  • mysql配置参数

    2010-12-09 14:04:48

    (1)显示配置参数 SHOW GLOBAL VARIABLES
  • mysql 性能监控 show status

    2010-02-01 20:25:23

    show status
    ## == 基于安全考虑 ==
    Aborted_connects

    试图连接到MySQL服务器而失败的连接数

    ## == 计算读写比例 ==

    Bytes_received

    从所有客户端接收到的字节数。

    Bytes_sent

    发送给所有客户端的字节数

    ## == sql语句执行次数 ==

    Com_xxx

    Com_xxx 语句计数变量表示每个xxx 语句执行的次数。每类语句有一个状态变量。例如,Com_delete和Com_insert分别统计DELETE 和INSERT语句执行的次数。

    ## == 临时表数目 ==

    Created_tmp_disk_tables

    服务器执行语句时在硬盘上自动创建的临时表的数量。

    Created_tmp_files

    mysqld已经创建的临时文件的数量。

    Created_tmp_files

    服务器执行语句时自动创建的内存中的临时表的数量。如果Created_tmp_disk_tables较大,可能要增加tmp_table_size值使临时 表基于内存而不基于硬盘。

    ## == 索引相关 ==

    Handler_read_first

    索引中第一条被读的次数。如果较高,它建议服务器正执行大量全索引扫描;例如,SELECT col1 FROM foo,假定col1有索引。

    Handler_read_key

    根据键读一行的请求数。如果较高,说明查询和表的索引正确。

    Handler_read_next

    按照键顺序读下一行的请求数。如果你用范围约束或如果执行索引扫描来查询索引列,该值增加。

    Handler_read_prev

    按照键顺序读前一行的请求数。该读方法主要用于优化ORDER BY ... DESC。

    Handler_read_rnd

    根据固定位置读一行的请求数。如果你正执行大量查询并需要对结果进行排序该值较高。你可能使用了大量需要MySQL扫描整个表的查询或你的连接没有正确使用键。

    Handler_read_rnd_next

    在数据文件中读下一行的请求数。如果你正进行大量的表扫描,该值较高。通常说明你的表索引不正确或写入的查询没有利用索引。

    ## == innodb的page监控 ==

    Innodb_buffer_pool_pages_data

    包含数据的页数(脏或干净)。

    Innodb_buffer_pool_pages_dirty

    当前的脏页数。

    Innodb_buffer_pool_pages_flushed

    要求清空的缓冲池页数。

    Innodb_buffer_pool_pages_free

    空页数。

    Innodb_buffer_pool_pages_latched

    在InnoDB缓冲池中锁定的页数。这是当前正读或写或由于其它原因不能清空或删除的页数。

    Innodb_buffer_pool_pages_misc

    忙的页数,因为它们已经被分配优先用作管理,例如行锁定或适用的哈希索引。该值还可以计算为Innodb_buffer_pool_pages_total - Innodb_buffer_pool_pages_free - Innodb_buffer_pool_pages_data。

    Innodb_buffer_pool_pages_total

    缓冲池总大小(页数)。

    ## == innodb缓冲池读写相关 ==

    Innodb_buffer_pool_read_ahead_rnd

    InnoDB初始化的“随机”read-aheads数。当查询以随机顺序扫描表的一大部分时发生。

    Innodb_buffer_pool_read_ahead_seq

    InnoDB初始化的顺序read-aheads数。当InnoDB执行顺序全表扫描时发生。

    Innodb_buffer_pool_read_requests

    InnoDB已经完成的逻辑读请求数。

    Innodb_buffer_pool_reads

    不能满足InnoDB必须单页读取的缓冲池中的逻辑读数量。

    Innodb_buffer_pool_wait_free

    一般情况,通过后台向InnoDB缓冲池写。但是,如果需要读或创建页,并且没有干净的页可用,则它还需要先等待页面清空。该计数器对等待实例进行记数。如果已经适当设置缓冲池大小,该值应小。

    Innodb_buffer_pool_write_requests

    向InnoDB缓冲池的写数量。

    ## == innodb读写相关 ==

    Innodb_data_pending_reads

    当前挂起的读数。

    Innodb_data_pending_writes

    当前挂起的写数。

    Innodb_data_read

    至此已经读取的数据数量(字节)。

    Innodb_data_reads

    数据读总数量。

    Innodb_data_writes

    数据写总数量。

    Innodb_data_written

    至此已经写入的数据量(字节)。

    Innodb_dblwr_writes, Innodb_dblwr_pages_written

    已经执行的双写操作数量和为此目的已经写好的页数。

    ## == innodb log相关 ==

    Innodb_log_waits

    我们必须等待的时间,因为日志缓冲区太小,我们在继续前必须先等待对它清空。

    Innodb_log_write_requests

    日志写请求数。

    Innodb_log_writes

    向日志文件的物理写数量。

    Innodb_os_log_fsyncs

    向日志文件完成的fsync()写数量。

    Innodb_os_log_pending_fsyncs

    挂起的日志文件fsync()操作数量。

    Innodb_os_log_pending_writes

    挂起的日志文件写操作。

    Innodb_os_log_written

    写入日志文件的字节数。

    ## == innodb page 相关 ==

    Innodb_page_size

    编译的InnoDB页大小(默认16KB)。许多值用页来记数;页的大小很容易转换为字节。

    Innodb_pages_created

    创建的页数。

    Innodb_pages_read

    读取的页数。

    Innodb_pages_written

    写入的页数。

    ## == innodb 行操作相关 ==

    Innodb_row_lock_current_waits

    当前等待的待锁定的行数。

    Innodb_row_lock_time

    行锁定花费的总时间,单位毫秒。

    Innodb_row_lock_time_avg

    行锁定的平均时间,单位毫秒。

    Innodb_row_lock_time_max

    行锁定的最长时间,单位毫秒。

    Innodb_row_lock_waits

    一行锁定必须等待的时间数。

    Innodb_rows_deleted

    从InnoDB表删除的行数。

    Innodb_rows_inserted

    插入到InnoDB表的行数。

    Innodb_rows_read

    从InnoDB表读取的行数。

    Innodb_rows_updated

    InnoDB表内更新的行数。

    ## == 查询结果缓存相关 ==

    QCACHE_free_blocks

    查询缓存内自由内存块的数量。

    QCACHE_free_memory

    用于查询缓存的自由内存的数量。

    QCACHE_hits

    查询缓存被访问的次数。

    QCACHE_inserts

    加入到缓存的查询数量。

    QCACHE_lowmem_prunes

    由于内存较少从缓存删除的查询数量。

    QCACHE_not_cached

    非缓存查询数(不可缓存,或由于query_cache_type设定值未缓存)。

    Qcache_queries_in_cache

    登记到缓存内的查询的数量。

    Qcache_total_blocks

    查询缓存内的总块数。

    ## == 慢sql,需报警 ==

    Slow_launch_threads

    创建时间超过slow_launch_time秒的线程数。

    Slow_queries

    查询时间超过long_query_time秒的查询的个数

    ## == table lock ==

    Table_locks_immediate

    立即获得的表的锁的次数。

    Table_locks_waited

    不能立即获得的表的锁的次数。如果该值较高,并且有性能问题,你应首先优化查询,然后拆分表或使用复制。

    ## == thread相关 ==

    Threads_cached

    线程缓存内的线程的数量。

    Threads_connected

    当前打开的连接的数量。

    Threads_created

    创建用来处理连接的线程数。如果Threads_created较大,你可能要增加thread_cache_size值。缓存访问率的计算方法Threads_created/Connections。

    Threads_running

    激活的(非睡眠状态)线程数。

    二、主从参数

    主从的参数,只要对从服务器到主服务的滞后时间,log条数加报警就可以了

    三、系统参数

    cpu:system,user,iowait,irq,softirq,idle

    load:1min,5min,15min

    mem:used,buffer,cache,free,swapfree,swapused

    traffic:in,out

    各个ip的连接数

    diskio
  • MYSQL------临时表的使用

    2009-11-26 14:36:38

    当工作在非常大的表上时,你可能偶尔需要运行很多查询获得一个大量数据的小的子集,不是对整个表运行这些查询,而是让MySQL每次找出所需的少数记录,将记录选择到一个临时表可能更快些,然后多这些表运行查询。

    创建临时表很容易,给正常的CREATE TABLE语句加上TEMPORARY关键字:

    CREATE TEMPORARY TABLE tmp_table (

    name VARCHAR(10) NOT NULL,

    value INTEGER NOT NULL

    )

    临时表将在你连接MySQL期间存在。当你断开时,MySQL将自动删除表并释放所用的空间。当然你可以在仍然连接的时候删除表并释放空间。

    DROP TABLE tmp_table

    如果在你创建名为tmp_table临时表时名为tmp_table的表在数据库中已经存在,临时表将有必要屏蔽(隐藏)非临时表tmp_table。

    如果你声明临时表是一个HEAP表,MySQL也允许你指定在内存中创建它:

    CREATE TEMPORARY TABLE tmp_table (

    name VARCHAR(10) NOT NULL,

    value INTEGER NOT NULL

    ) TYPE = HEAP

    因为HEAP表存储在内存中,你对它运行的查询可能比磁盘上的临时表快些。然而,HEAP表与一般的表有些不同,且有自身的限制。详见MySQL参考手册。

    正如前面的建议,你应该测试临时表看看它们是否真的比对大量数据库运行查询快。如果数据很好地索引,临时表可能一点不快。

     
  • mysql -----show processlist命令

    2009-10-19 18:09:10

    (1)SHOW processlist命令的输出结果显示了有哪些线程在运行
    (2)command列,显示当前连接的执行的命令,一般就是休眠(sleep),查询(query),连接(connect
    (3)time列,此这个状态持续的时间,单位是秒
    (4)state列,显示使用当前连接的sql语句的状态
     
       Checking table
     正在检查数据表(这是自动的)。
     Closing tables
     正在将表中修改的数据刷新到磁盘中,同时正在关闭已经用完的表。这是一个很快的操作,如果不是这样的话,就应该确认磁盘空间是否已经满了或者磁盘是否正处于重负中。

     Connect Out
     复制从服务器正在连接主服务器。

     Copying to tmp table on disk
     由于临时结果集大于tmp_table_size,正在将临时表从内存存储转为磁盘存储以此节省内存。

     Creating tmp table
     正在创建临时表以存放部分查询结果。

     deleting from main table
     服务器正在执行多表删除中的第一部分,刚删除第一个表。

     deleting from reference tables
     服务器正在执行多表删除中的第二部分,正在删除其他表的记录。

     Flushing tables
     正在执行FLUSH TABLES,等待其他线程关闭数据表。

     Killed
     发送了一个kill请求给某线程,那么这个线程将会检查kill标志位,同时会放弃下一个kill请求。MySQL会在每次的主循环中检查kill标志位,不过有些情况下该线程可能会过一小段才能死掉。如果该线程程被其他线程锁住了,那么kill请求会在锁释放时马上生效。

     Locked
     被其他查询锁住了。

     Sending data
     正在处理SELECT查询的记录,同时正在把结果发送给客户端。

     Sorting for group
     正在为GROUP BY做排序。

     Sorting for order
     正在为ORDER BY做排序。

     Opening tables
     这个过程应该会很快,除非受到其他因素的干扰。例如,在执ALTER TABLELOCK TABLE语句行完以前,数据表无法被其他线程打开。正尝试打开一个表。

     Removing duplicates
     正在执行一个SELECT DISTINCT方式的查询,但是MySQL无法在前一个阶段优化掉那些重复的记录。因此,MySQL需要再次去掉重复的记录,然后再把结果发送给客户端。

     Reopen table
     获得了对一个表的锁,但是必须在表结构修改之后才能获得这个锁。已经释放锁,关闭数据表,正尝试重新打开数据表。

     Repair by sorting
     修复指令正在排序以创建索引。

     Repair with keycache
     修复指令正在利用索引缓存一个一个地创建新索引。它会比Repair by sorting慢些。

     Searching rows for update
     正在讲符合条件的记录找出来以备更新。它必须在UPDATE要修改相关的记录之前就完成了。

     Sleeping
     正在等待客户端发送新请求
    .
     
    System lock
     正在等待取得一个外部的系统锁。如果当前没有运行多个mysqld服务器同时请求同一个表,那么可以通过增加--skip-external-locking参数来禁止外部系统锁。

     Upgrading lock
     INSERT DELAYED正在尝试取得一个锁表以插入新记录。

     Updating
     正在搜索匹配的记录,并且修改它们。

     User Lock
     正在等待GET_LOCK()

     Waiting for tables
     该线程得到通知,数据表结构已经被修改了,需要重新打开数据表以取得新的结构。然后,为了能的重新打开数据表,必须等到所有其他线程关闭这个表。以下几种情况下会产生这个通知:FLUSH TABLES tbl_name, ALTER TABLE, RENAME TABLE, REPAIR TABLE, ANALYZE TABLE,OPTIMIZE TABLE

     waiting for handler insert
     INSERT DELAYED已经处理完了所有待处理的插入操作,正在等待新的请求。

  • MYSQL 查看表结构语句

    2009-01-12 13:54:49

    (1)show columns from 表名 或 desc 表名

    Key那一栏,可能会有4种值,即'啥也没有','PRI','UNI','MUL'
    1. 如果Key是空的, 那么该列值的可以重复, 表示该列没有索引, 或者是一个非唯一的复合索引的非前导列
    2. 如果Key是PRI,  那么该列是主键的组成部分
    3. 如果Key是UNI,  那么该列是一个唯一值索引的第一列(前导列),并不能含有空值(NULL)
    4. 如果Key是MUL,  那么该列的值可以重复, 该列是一个非唯一索引的前导列(第一列)或者是一个唯一性索引的组成部分但是可以含有空值NULL

    如果对于一个列的定义,同时满足上述4种情况的多种,比如一个列既是PRI,又是UNI
    那么"desc 表名"的时候,显示的Key值按照优先级来显示 PRI->UNI->MUL
    那么此时,显示PRI

    一个唯一性索引列可以显示为PRI,并且该列不能含有空值,同时该表没有主键

    一个唯一性索引列可以显示为MUL, 如果多列构成了一个唯一性复合索引
    因为虽然索引的多列组合是唯一的,比如ID+NAME是唯一的,但是没一个单独的列依然可以有重复的值
    只要ID+NAME是唯一的即可

     

    (2)show create table 表名

  • SQL语句优化的原则

    2008-12-04 16:13:13

    1、使用索引来更快地遍历表。
       缺省情况下建立的索引是非群集索引,但有时它并不是最佳的。在非群集索引
    下,数据在物理上随机存放在数据页上。合理的索引设计要建立在
    对各种查询的分析和预测上。一般来说:①.有大量重复值、且经常有范围查询
    (between, > ,<  ,> =,<  =)和order by、group by发生的列,可考
    虑建立群集索引;②.经常同时存取多列,且每列都含有重复值可考虑建立组合索引
    ;③.组合索引要尽量使关键查询形成索引覆盖,其前导列一定
    是使用最频繁的列。索引虽有助于提高性能但不是索引越多越好,恰好相反过多的索
    引会导致系统低效。用户在表中每加进一个索引,维护索引集
    合就要做相应的更新工作。
    2、IS NULL 与 IS NOT NULL
       不能用null作索引,任何包含null值的列都将不会被包含在索引中。即使索引有
    多列这样的情况下,只要这些列中有一列含有null,该列就会从
    索引中排除。也就是说如果某列存在空值,即使对该列建索引也不会提高性能。任何
    在where子句中使用is null或is not null的语句优化器是不允
    许使用索引的。
    3、IN和EXISTS
       EXISTS要远比IN的效率高。里面关系到full table scan和range scan。几乎将所
    有的IN操作符子查询改写为使用EXISTS的子查询。
    4、在海量查询时尽量少用格式转换。
    5、当在SQL SERVER 2000中,如果存储过程只有一个参数,并且是OUTPUT类型的,必
    须在调用这个存储过程的时候给这个参数一个初始的值,否则
    会出现调用错误。
    6、ORDER BY和GROPU BY
       使用ORDER BY和GROUP BY短语,任何一种索引都有助于SELECT的性能提高。注意
    如果索引列里面有NULL值,Optimizer将无法优化。
    7、任何对列的操作都将导致表扫描,它包括数据库函数、计算表达式等等,查询时
    要尽可能将操作移至等号右边。
    8、IN、OR子句常会使用工作表,使索引失效。如果不产生大量重复值,可以考虑把
    子句拆开。拆开的子句中应该包含索引。
    9、SET SHOWPLAN_ALL ON 查看执行方案。DBCC检查数据库数据完整性。
    DBCC(DataBase Consistency Checker)是一组用于验证 SQL Server 数据
    库完整性的程序。
    10、慎用游标
       在某些必须使用游标的场合,可考虑将符合条件的数据行转入临时表中,再对临
    时表定义游标进行操作,这样可使性能得到明显提高。
    总结:所谓优化即WHERE子句利用了索引,不可优化即发生了表扫描或额外开销。经
    验显示,SQL Server性能的最大改进得益于逻辑的数据库设计、
    索引设计和查询设计方面。反过来说,最大的性能问题常常是由其中这些相同方面中
    的不足引起的。其实SQL优化的实质就是在结果正确的前提下,
    用优化器可以识别的语句,充份利用索引,减少表扫描的I/O次数,尽量避免表搜索
    的发生。其实SQL的性能优化是一个复杂的过程,上述这些只是
    在应用层次的一种体现,深入研究还会涉及数据库层的资源配置、网络层的流量控制
    以及操作系统层的总体设计。
  • sql 主键

    2008-11-26 10:34:18

    1,主键非空,也就是说被设定为主键的列在插入数据的时候就不能为空,如果为空SQL就会报错。
    2,主键是唯一的,一个表通过一个主键可以确定一条记录,有一条记录的主键是SF110如果你再向里面插入SF110的记录SQL就会报错。
    3,有时可以用两个字段来建立主键,这叫联合主键。这种情况出现在当一个字段无法唯一的时候要借助另一个字段来确保唯一性的时候。

    注:主键是为了避免重复的单据出现

    SQL> create table test_pri(a number(1), b number(1));
    表已创建。
    --1.创建主键,则自动创建同名唯一索引
    --1.1创建主键,主键约束和唯一索引同时创建
    SQL> alter table test_pri add constraint pk_test_pri_a primary key(a);
    表已更改。
    SQL> select CONSTRAINT_NAME, TABLE_NAME, INDEX_NAME
    2 from user_constraints where table_name = ''TEST_PRI'';
    CONSTRAINT_NAME TABLE_NAME INDEX_NAME
    ----------------- ------------ -------------
    PK_TEST_PRI_A TEST_PRI PK_TEST_PRI_A
    SQL> select INDEX_NAME, INDEX_TYPE, TABLE_NAME, UNIQUENESS
    2 from user_indexes where table_name = ''TEST_PRI'';
    INDEX_NAME INDEX_TYPE TABLE_NAME UNIQUENES
    ---------------- ------------ ------------ ---------
    PK_TEST_PRI_A NORMAL TEST_PRI UNIQUE
    --1.2 删除主键,主键约束和对应的唯一索引都删除了
    SQL> alter table test_pri drop constraint pk_test_pri_a;
    表已更改。
    SQL> select CONSTRAINT_NAME, TABLE_NAME, INDEX_NAME
    2 from user_constraints where table_name = ''TEST_PRI'';
    未选定行
    SQL> select INDEX_NAME, INDEX_TYPE, TABLE_NAME, UNIQUENESS
    2 from user_indexes where table_name = ''TEST_PRI'';
    未选定行
    --1.3其实删除主键时可以选择保留索引的
    SQL> alter table test_pri add constraint pk_test_pri_a primary key(a);
    表已更改。
    SQL> alter table test_pri drop constraint pk_test_pri_a keep index;
    表已更改。
    SQL> select CONSTRAINT_NAME, TABLE_NAME, INDEX_NAME
    2 from user_constraints where table_name = ''TEST_PRI'';
    未选定行
    SQL> select INDEX_NAME, INDEX_TYPE, TABLE_NAME, UNIQUENESS
    2 from user_indexes where table_name = ''TEST_PRI'';
    INDEX_NAME INDEX_TYPE TABLE_NAME UNIQUENES
    --------------- ----------- ----------- ---------
    PK_TEST_PRI_A NORMAL TEST_PRI UNIQUE


    --2.在存在唯一索引的列上创建主键,则只创建主键约束,同时将该约束与已有唯一索引关联上(名称可以不一致)
    SQL> drop index pk_test_pri_a;
    索引已丢弃。
    --2.1 先创建唯一索引,再创建主键,名称可以不一致
    SQL> create unique index pk_test_pri_a on test_pri(a);
    索引已创建。
    SQL> alter table test_pri add constraint pk_test_pri primary key(a);
    表已更改。
    SQL> select INDEX_NAME, INDEX_TYPE, TABLE_NAME, UNIQUENESS
    2 from user_indexes where table_name = ''TEST_PRI'';
    INDEX_NAME INDEX_TYPE TABLE_NAME UNIQUENES
    --------------- ----------- ------------ ---------
    PK_TEST_PRI_A NORMAL TEST_PRI UNIQUE
    SQL> select CONSTRAINT_NAME, TABLE_NAME, INDEX_NAME
    2 from user_constraints where table_name = ''TEST_PRI'';
    CONSTRAINT_NAME TABLE_NAME INDEX_NAME
    ------------------ ------------ -------------
    PK_TEST_PRI TEST_PRI PK_TEST_PRI_A
    --2.2 不可删除存在主键约束的唯一索引
    SQL> drop index PK_TEST_PRI_A;
    drop index PK_TEST_PRI_A
    *
    ERROR 位于第 1 行:
    ORA-02429: 无法删除用于强制唯一/主键的索引
    --2.3虽然两者名称不一致,但也是关联在一块的:删除约束,则对应的索引同时删除
    SQL> alter table test_pri drop constraint pk_test_pri;
    表已更改。
    SQL> select INDEX_NAME, INDEX_TYPE, TABLE_NAME, UNIQUENESS
    2 from user_indexes where table_name = ''TEST_PRI'';
    未选定行
    SQL> select CONSTRAINT_NAME, TABLE_NAME, INDEX_NAME
    2 from user_constraints where table_name = ''TEST_PRI'';
    未选定行
    SQL>
  • SQL中删除多余的相同记录

    2008-11-25 15:56:12

    (1)方法1

    declare @max integer,@id integer
    declare cur_rows cursor local for
    select id,count(*) from 表名 group by id having count(*) > 1
    open cur_rows
    fetch cur_rows into @id,@max
    while @@fetch_status=0
    begin
    select @max = @max -1
    set rowcount @max
    delete from 表名 where id = @id
    fetch cur_rows into @id,@max
    end
    close cur_rows
    set rowcount 0

    注意:
    set rowcount { number | @number_var }
    number | @number_var 在停止特定查询之前要处理的行数(整数)。

     

  • SQL 函数

    2008-11-21 10:32:36

    (1)substring
    substring(string, number, number?)

    substring("12345",2,3) 以下函数调用返回“234”

    (2)charindex 函数返回字符或者字符串在另一个字符串中的起始位置。CHARINDEX函数调用方法如下: CHARINDEX ( expression1 , expression2 [ , start_location ] )

    CHARINDEX('SQL', 'Microsoft SQL Server')    返回11
  • 优化总结

    2008-11-12 18:13:17

    (1)在查询的时候group by后的字段顺序按所建索引的字段排列

    (2)分析存储过程的时候对整个过程中加入select 标识,getdate(),以便分析出那快过程速度慢

    (3)部分游标使用的时候可以改为临时表来实现(临时表可以是存在数据库的中的临时表)

    truncate table 表名      (删除表所有行)

     

     

  • 建索引要考虑的问题

    2008-11-11 14:38:15

    使用索引的意义

    • 索引在数据库中的作用类似于目录在书籍中的作用,用来提高查找信息的速度。
    • 使用索引查找数据,无需对整表进行扫描,可以快速找到所需数据。

    使用索引的代价

    • 索引需要占用数据表以外的物理存储空间。
    • 创建索引和维护索引要花费一定的时间。
    • 当对表进行更新操作时,索引需要被重建,这样降低了数据的维护速度。

    创建索引的列

    • 主键
    • 外键或在表联接操作中经常用到的列
    • 在经常查询的字段上最好建立索引

    不创建索引的列

    • 很少在查询中被引用
    • 包含较少的惟一值
    • 定义为 text、ntext 或者 image 数据类型的列
  • 清除数据库缓存的语句

    2008-11-11 14:28:36

    DBCC   DROPCLEANBUFFERS  

    从缓冲池中删除所有清除缓冲区。

    DBCC   FREEPROCCACHE  

    从过程缓存中删除所有元素。

    DBCC FREESYSTEMCACHE ( 'ALL' )

    从所有缓存中释放所有未使用的缓存条目。

    SQL Server 2005 数据库引擎会事先在后台清理未使用的缓存条目,以使内存可用于当前条目。但是,可以使用此命令从所有缓存中手动删除未使用的条目。

    另外还可以 sp_cursor_list 查看全部游标  

    DBCC   OPENTRAN查看数据库打开事务状态等  

  • INDEXPROPERTY 索引的度查询

    2008-11-11 13:30:13

     INDEXPROPERTY 中的几个查询属性

    属性 说明

    IndexDepth

    索引的深度。

    索引级别数。NULL = XML 索引或输入无效。

    IndexFillFactor

    创建索引或最后重新生成索引时使用的填充因子值。

    填充因子

    IndexID

    指定表或索引视图上索引的索引 ID。

    索引 ID

    IsAutoStatistics

    统计信息是由 ALTER DATABASE 的 AUTO_CREATE_STATISTICS 选项生成的。

    1=True 0=False 或 XML 索引。

    IsClustered

    索引是聚集的。

    1=True 0=False 或 XML 索引。

    IsDisabled

    索引被禁用。

    1=True 0=False NULL=输入无效。

    IsFulltextKey

    索引是表的全文键。

    1=True 0=False 或 XML 索引。 NULL=输入无效。

    IsHypothetical

    索引是假设的,不能直接用作数据访问路径。假设索引包含列级统计信息,由数据库引擎优化顾问维护和使用。

    1=True 0=False 或 XML 索引 NULL=输入无效。

    IsPadIndex

    索引指定每个内部节点上将要保持空闲的空间。

    1=True 0=False 或 XML 索引。

    IsPageLockDisallowed

    通过 ALTER INDEX 的 ALLOW_PAGE_LOCKS 选项设置的页锁定值。

    1=不允许页锁定0=允许页锁定。 NULL=输入无效。

    IsRowLockDisallowed

    通过 ALTER INDEX 的 ALLOW_ROW_LOCKS 选项设置的行锁定值。

    1=不允许行锁定。 0=允许行锁定。 NULL = 输入无效。

    IsStatistics

    index_or_statistics_name 是通过 CREATE STATISTICS 语句或 ALTER DATABASE 的 AUTO_CREATE_STATISTICS 选项创建的统计信息。

    1=True     0=False 或 XML 索引。

    IsUnique

    索引是唯一的。

    1=True 0=False 或 XML 索引。

    如:查看索引的深度SQL 脚本如下:

    select INDEXPROPERTY (OBJECT_ID('ChargeHeap'),'ChargeHeap_NCInd','IndexDepth')

    其中的 'ChargeHeap' 为我们要查看索引所在的表名,'ChargeHeap_NCInd' 为所要查看的索引名,'IndexDepth' 为所要查看的索引属性。

  • 三种调优查询的主要的方法

    2008-11-10 18:05:35

    1、使用SET STATISTICS IO 检查查询所产生的读和写
    2、使用SET STATISTICS TIME检查查询的运行时间
    3、使用SET SHOWPLAN 分析查询的查询计划

    SET STATISTICS IO
    命令SET STATISTICS IO ON 强制SQL Server 报告执行事务时I/O的实际活动。它不能与SET NOEXEC ON 选项配对使用,因为它仅仅对监测实际执行命令的I/O活动有意义。一旦这个选项被打开,每个查询产生包括I/O统计信息的额外输出。为了关闭这个选项,执行SET STATISTICS IO OFF.

    :这些命令也能在 Sybase Adaptive Server中运行,虽然结果集可能看起来有点不同

    扫描统计告诉我们扫描执行的数量,逻辑读显示的是从缓存中读出来的页面的数量,物理读显示的是从磁盘中读的页面的数量,Read-ahead 读显示了放置在缓存中用于将来读操作的页面数量。

    输出项  含义 
    Table
    表的名称。

    Scan count (扫描计数)
    执行的索引或表扫描数。

    logical reads (逻辑读取)
    从数据缓存读取的页数。

    physical reads (物理读取)
    从磁盘读取的页数。

    read-ahead reads (预读)
    为进行查询而放入缓存的页数。

    lob logical reads (lob 逻辑读取)
    从数据缓存读取的 text、ntext、image 或大值类型 (varchar(max)、nvarchar(max)、varbinary(max)) 页的数目。

    lob physical reads(lob 物理读取)
    从磁盘读取的 text、ntext、image 或大值类型页的数目。

    lob read-ahead reads (lob 预读)
    为进行查询而放入缓存的 text、ntext、image 或大值类型页的数目。

    SET STATISTICS TIME
    一个事务的实耗时间是一个不稳定的测量,因为这些时间与在服务器上其他用户的活动有关。然而,相比那些对你的用户没有任何意义的数据页数字,它提供了一些实际的测量。他们关心等待查询返回的时间消耗,不关心数据的缓存和有效的read-ahead。SET STATISTICS TIME ON命令报告下面的查询的实际占用时间和CPU使用情况。执行SET STATISTICS TIME OFF禁止这个选项。

    注意实耗时间和CPU时间是以毫秒显示。这个数字在你的电脑上可能会改变(但是不要尝试与我们的笔记本电脑比较你机器的性能,因为这不是代表性的指标)。而且,每次你执行这个脚本,考虑到你的SQL Server还在处理一些其他事务,你得到的统计信息都可能有一点不同。

    SHOWPLAN 输出和分析
    SET SHOWPLAN_TEXT { ON | OFF }
    默认情况下,SHOWPLAN_TEXT ON使得你正在审查的代码不被执行。而是,SQL Server 编译这些代码并且显示这个查询的执行计划。直到你发出SET.SHOWPLAN_TEXT OFF命令后它才停止。

    ◆SET NOEXEC{ ON | OFF}: 检查你的Transact-SQL代码的语法,包括编译该代码但不执行。当使用延迟名字解析时,这对检查一个查询语句的语法是很有用的。即,当一个表还没有创建时,你就可以检查基于该表的查询语句的语法。
    ◆SET FMTONLY{ ON | OFF }:仅向客户端返回查询的元数据。对于SELECT语句,通常仅返回列头。
    ◆SET PARSEONLY { ON | OFF }:检查你的Transact-SQL代码的语法,但不编译或执行该代码。


     

  • SQL 中having

    2008-11-10 13:47:21

    HAVING 与 WHERE 类似,可用来决定选择哪个记录。在使用 GROUP BY对这些记录分组后,HAVING 会决定应显示的记录:

    SELECT CategoryID,

    Sum(UnitsInStock)

    FROM Products

    GROUP BY CategoryID

    HAVING Sum(UnitsInStock) > 100 And Like "BOS*";

    一个 HAVING 子句最多可包含 40 个表达式,并由诸如 And Or 之类的逻辑操作符来链接这些表达式。

  • SQL提高速度注意事项

    2008-11-10 12:11:01

    1、 只返回需要的数据
    返回数据到客户端至少需要数据库提取数据、网络传输数据、客户端接收数据以及客户端处理数据等环节,如果返回不需要的数据,就会增加服务器、网络和客户端的无效劳动,其害处是显而易见的,避免这类事件需要注意:
    A、横向来看,不要写SELECT *的语句,而是选择你需要的字段。
    B、 纵向来看,合理写WHERE子句,不要写没有WHERE的SQL语句。
    C、 注意SELECT INTO后的WHERE子句,因为SELECT INTO把数据插入到临时表,这个过程会锁定一些系统表,如果这个WHERE子句返回的数据过多或者速度太慢,会造成系统表长期锁定,诸塞其他进程。
    D、对于聚合查询,可以用HAVING子句进一步限定返回的行。

    2、尽量少做重复的工作
    这一点和上一点的目的是一样的,就是尽量减少无效工作,但是这一点的侧重点在客户端程序,需要注意的如下:
    A、控制同一语句的多次执行,特别是一些基础数据的多次执行是很多程序员很少注意的。
    B、减少多次的数据转换,也许需要数据转换是设计的问题,但是减少次数是程序员可以做到的。
    C、杜绝不必要的子查询和连接表,子查询在执行计划一般解释成外连接,多余的连接表带来额外的开销。
    D、合并对同一表同一条件的多次UPDATE,比如
    UPDATE EMPLOYEE SET FNAME=’HAIWER’ WHERE EMP_ID=’ VPA30890F’
    UPDATE EMPLOYEE SET LNAME=’YANG’ WHERE EMP_ID=’ VPA30890F’
    这两个语句应该合并成以下一个语句
    UPDATE EMPLOYEE SET FNAME=’HAIWER’,LNAME=’YANG’BR>WHERE EMP_ID=’ VPA30890F’
    E、UPDATE操作不要拆成DELETE操作+INSERT操作的形式,虽然功能相同,但是性能差别是很大的。
    F、不要写一些没有意义的查询,比如
    SELECT * FROM EMPLOYEE WHERE 1=2

    3、注意事务和锁
    事务是数据库应用中和重要的工具,它有原子性、一致性、隔离性、持久性这四个属性,很多操作我们都需要利用事务来保证数据的正确性。在使用事务中我们需要做到尽量避免死锁、尽量减少阻塞。具体以下方面需要特别注意:
    A、事务操作过程要尽量小,能拆分的事务要拆分开来。
    B、事务操作过程不应该有交互,因为交互等待的时候,事务并未结束,可能锁定了很多资源。
    C、事务操作过程要按同一顺序访问对象。
    D、提高事务中每个语句的效率,利用索引和其他方法提高每个语句的效率可以有效地减少整个事务的执行时间。
    E、尽量不要指定锁类型和索引,SQL SERVER允许我们自己指定语句使用的锁类型和索引,但是一般情况下,SQL SERVER优化器选择的锁类型和索引是在当前数据量和查询条件下是最优的,我们指定的可能只是在目前情况下更有,但是数据量和数据分布在将来是会变化的。
    F、 查询时可以用较低的隔离级别,特别是报表查询的时候,可以选择最低的隔离级别(未提交读)。

    4、注意临时表和表变量的用法
    在复杂系统中,临时表和表变量很难避免,关于临时表和表变量的用法,需要注意:
    A、如果语句很复杂,连接太多,可以考虑用临时表和表变量分步完成。
    B、如果需要多次用到一个大表的同一部分数据,考虑用临时表和表变量暂存这部分数据。
    C、如果需要综合多个表的数据,形成一个结果,可以考虑用临时表和表变量分步汇总这多个表的数据。
    D、其他情况下,应该控制临时表和表变量的使用。
    E、关于临时表和表变量的选择,很多说法是表变量在内存,速度快,应该首选表变量,但是在实际使用中发现,这个选择主要考虑需要放在临时表的数据量,在数据量较多的情况下,临时表的速度反而更快。
    F、关于临时表产生使用SELECT INTO和CREATE TABLE + INSERT INTO的选择,我们做过测试,一般情况下,SELECT INTO会比CREATE TABLE + INSERT INTO的方法快很多,但是SELECT INTO会锁定TEMPDB的系统表SYSOBJECTS、SYSINDEXES、SYSCOLUMNS,在多用户并发环境下,容易阻塞其他进程,所以我的建议是,在并发系统中,尽量使用CREATE TABLE + INSERT INTO,而大数据量的单个语句使用中,使用SELECT INTO。
    G、注意排序规则,用CREATE TABLE建立的临时表,如果不指定字段的排序规则,会选择TEMPDB的默认排序规则,而不是当前数据库的排序规则。如果当前数据库的排序规则和TEMPDB的排序规则不同,连接的时候就会出现排序规则的冲突错误。一般可以在CREATE TABLE建立临时表时指定字段的排序规则为DATABASE_DEFAULT来避免上述问题。

    5、子查询的用法
    子查询是一个 SELECT 查询,它嵌套在 SELECT、INSERT、UPDATE、DELETE 语句或其它子查询中。任何允许使用表达式的地方都可以使用子查询。
    子查询可以使我们的编程灵活多样,可以用来实现一些特殊的功能。但是在性能上,往往一个不合适的子查询用法会形成一个性能瓶颈。
    如果子查询的条件中使用了其外层的表的字段,这种子查询就叫作相关子查询。相关子查询可以用IN、NOT IN、EXISTS、NOT EXISTS引入。
    关于相关子查询,应该注意:
    A、NOT IN、NOT EXISTS的相关子查询可以改用LEFT JOIN代替写法。比如:
    SELECT PUB_NAME FROM PUBLISHERS
    WHERE PUB_ID NOT IN (SELECT PUB_ID FROM TITLES WHERE TYPE = 'BUSINESS')
    可以改写成:
    SELECT A.PUB_NAME FROM PUBLISHERS A LEFT JOIN TITLES B
    ON B.TYPE = 'BUSINESS' AND A.PUB_ID=B. PUB_ID WHERE B.PUB_ID IS NULL

    SELECT TITLE FROM TITLES
    WHERE NOT EXISTS  (SELECT TITLE_ID FROM SALES  WHERE TITLE_ID = TITLES.TITLE_ID)
    可以改写成:
    SELECT TITLE FROM TITLES LEFT JOIN SALES
    ON SALES.TITLE_ID = TITLES.TITLE_ID
    WHERE SALES.TITLE_ID IS NULL
    B、如果保证子查询没有重复 ,IN、EXISTS的相关子查询可以用INNER JOIN 代替。比如:
    SELECT PUB_NAME
    FROM PUBLISHERS
    WHERE PUB_ID IN
       (SELECT PUB_ID
       FROM TITLES
       WHERE TYPE = 'BUSINESS')
    可以改写成:
    SELECT DISTINCT A.PUB_NAME
    FROM PUBLISHERS A INNER JOIN TITLES B
    ON        B.TYPE = 'BUSINESS' AND
              A.PUB_ID=B. PUB_ID

    C、IN的相关子查询用EXISTS代替,比如
    SELECT PUB_NAME
    FROM PUBLISHERS
    WHERE PUB_ID IN
       (SELECT PUB_ID
       FROM TITLES
       WHERE TYPE = 'BUSINESS')
    可以用下面语句代替:
    SELECT PUB_NAME
    FROM PUBLISHERS
    WHERE EXISTS
       (SELECT 1
       FROM TITLES
       WHERE TYPE = 'BUSINESS' AND
       PUB_ID= PUBLISHERS.PUB_ID)
    D、不要用COUNT(*)的子查询判断是否存在记录,最好用LEFT JOIN或者EXISTS,比如有人写这样的语句:
    SELECT JOB_DESC FROM JOBS
    WHERE (SELECT COUNT(*) FROM EMPLOYEE WHERE JOB_ID=JOBS.JOB_ID)=0
    应该改成:
    SELECT JOBS.JOB_DESC FROM JOBS LEFT JOIN EMPLOYEE  
    ON EMPLOYEE.JOB_ID=JOBS.JOB_ID
    WHERE EMPLOYEE.EMP_ID IS NULL

    SELECT JOB_DESC FROM JOBS
    WHERE (SELECT COUNT(*) FROM EMPLOYEE WHERE JOB_ID=JOBS.JOB_ID)<>0
    应该改成:
    SELECT JOB_DESC FROM JOBS
    WHERE EXISTS (SELECT 1 FROM EMPLOYEE WHERE JOB_ID=JOBS.JOB_ID)

    6、 慎用游标
    数据库一般的操作是集合操作,也就是对由WHERE子句和选择列确定的结果集作集合操作,游标是提供的一个非集合操作的途径。一般情况下,游标实现的功能往往相当于客户端的一个循环实现的功能,所以,大部分情况下,我们把游标功能搬到客户端。
    游标是把结果集放在服务器内存,并通过循环一条一条处理记录,对数据库资源(特别是内存和锁资源)的消耗是非常大的,所以,我们应该只有在没有其他方法的情况下才使用游标。
    另外,我们可以用SQL SERVER的一些特性来代替游标,达到提高速度的目的。
    A、字符串连接的例子
    这是论坛经常有的例子,就是把一个表符合条件的记录的某个字符串字段连接成一个变量。比如需要把JOB_ID=10的EMPLOYEE的FNAME连接在一起,用逗号连接,可能最容易想到的是用游标:
        DECLARE @NAME VARCHAR(20)
        DECLARE @NAME VARCHAR(1000)
        DECLARE NAME_CURSOR CURSOR FOR
        SELECT FNAME FROM EMPLOYEE WHERE JOB_ID=10 ORDER BY EMP_ID
        OPEN NAME_CURSOR
        FETCH NEXT FROM RNAME_CURSOR INTO @NAME
        WHILE @@FETCH_STATUS = 0
        BEGIN
          SET @NAMES = ISNULL(@NAMES+’,’,’’)+@NAME
          FETCH NEXT FROM NAME_CURSOR  INTO @NAME  
        END
        CLOSE NAME_CURSOR
        DEALLOCATE NAME_CURSOR
    可以如下修改,功能相同:
       DECLARE @NAME VARCHAR(1000)
       SELECT @NAMES = ISNULL(@NAMES+’,’,’’)+FNAME
          FROM EMPLOYEE WHERE JOB_ID=10 ORDER BY EMP_ID
    B、 用CASE WHEN 实现转换的例子
    很多使用游标的原因是因为有些处理需要根据记录的各种情况需要作不同的处理,实际上这种情况,我们可以用CASE WHEN语句进行必要的判断处理,而且CASE WHEN是可以嵌套的。比如:
    表结构:
    CREATE TABLE 料件表(
    料号           VARCHAR(30),
    名称           VARCHAR(100),
    主单位         VARCHAR(20),
    单位1         VARCHAR(20),
    单位1参数      NUMERIC(18,4),
    单位2         VARCHAR(20),
    单位2参数      NUMERIC(18,4)
    )
    GO
    CREATE TABLE 入库表(
    时间               DATETIME,
    料号               VARCHAR(30),
    单位               INT,
    入库数量           NUMERIC(18,4),
    损坏数量           NUMERIC(18,4)
    )
    GO
    其中,单位字段可以是0,1,2,分别代表主单位、单位1、单位2,很多计算需要统一单位,统一单位可以用游标实现:
    DECLARE @料号     VARCHAR(30),
            @单位   INT,
            @参数      NUMERIC(18,4),
    DECLARE CUR CURSOR FOR
            SELECT 料号,单位 FROM 入库表 WHERE 单位 <>0
    OPEN CUR
    FETCH NEXT FROM CUR INTO @料号,@单位
    WHILE @@FETCH_STATUS<>-1
    BEGIN
      IF @单位=1
      BEGIN
        SET @参数=(SELECT 单位1参数 FROM 料件表 WHERE 料号 =@料号)
        UPDATE 入库表 SET 数量=数量*@参数,损坏数量=损坏数量*@参数,单位=1 WHERE CURRENT OF CUR
      END
      IF @单位=2
      BEGIN
        SET @参数=(SELECT 单位1参数 FROM 料件表 WHERE 料号 =@料号)
        UPDATE 入库表 SET 数量=数量*@参数,损坏数量=损坏数量*@参数,单位=1 WHERE CURRENT OF CUR
      END
      FETCH NEXT FROM CUR INTO @料号,@单位
    END
    CLOSE CUR
    DEALLOCATE CUR
    可以改写成:
    UPDATE A SET  
    数量=CASE A.单位 WHEN 1 THEN      A.数量*B. 单位1参数 
                    WHEN 2 THEN         A.数量*B. 单位2参数 
                    ELSE A.数量
    END,                  
    损坏数量= CASE A.单位 WHEN 1 THEN    A. 损坏数量*B. 单位1参数
                        WHEN 2 THEN         A. 损坏数量*B. 单位2参数
                        ELSE A. 损坏数量
    END,
    单位=1  
    FROM入库表 A, 料件表 B
    WHERE    A.单位<>1      AND
             A.料号=B.料号
    C、 变量参与的UPDATE语句的例子
    SQL ERVER的语句比较灵活,变量参与的UPDATE语句可以实现一些游标一样的功能,比如:

    SELECT A,B,C,CAST(NULL AS INT) AS 序号
    INTO #T
    FROM 表
    ORDER BY A ,NEWID()
    产生临时表后,已经按照A字段排序,但是在A相同的情况下是乱序的,这时如果需要更改序号字段为按照A字段分组的记录序号,就只有游标和变量参与的UPDATE语句可以实现了,这个变量参与的UPDATE语句如下:
    DECLARE @A INT
    DECLARE @序号 INT
    UPDATE #T SET
       @序号=CASE WHEN A=@A THEN @序号+1 ELSE 1 END,
       @A=A,
       序号=@序号
    D、如果必须使用游标,注意选择游标的类型,如果只是循环取数据,那就应该用只进游标(选项FAST_FORWARD),一般只需要静态游标(选项STATIC)。
    E、注意动态游标的不确定性,动态游标查询的记录集数据如果被修改,会自动刷新游标,这样使得动态游标有了不确定性,因为在多用户环境下,如果其他进程或者本身更改了纪录,就可能刷新游标的记录集。

    7、 尽量使用索引
    建立索引后,并不是每个查询都会使用索引,在使用索引的情况下,索引的使用效率也会有很大的差别。只要我们在查询语句中没有强制指定索引,索引的选择和使用方法是SQLSERVER的优化器自动作的选择,而它选择的根据是查询语句的条件以及相关表的统计信息,这就要求我们在写SQL语句的时候尽量使得优化器可以使用索引。
    为了使得优化器能高效使用索引,写语句的时候应该注意:
    A、不要对索引字段进行运算,而要想办法做变换,比如
    SELECT ID FROM T WHERE NUM/2=100
    应改为:
    SELECT ID FROM T WHERE NUM=100*2
    SELECT ID FROM T WHERE NUM/2=NUM1
    如果NUM有索引应改为:
    SELECT ID FROM T WHERE NUM=NUM1*2
    如果NUM1有索引则不应该改。
    发现过这样的语句:
    SELECT 年,月,金额 FROM 结余表
    WHERE 100*年+月=2007*100+10
    应该改为:
    SELECT 年,月,金额 FROM 结余表
    WHERE 年=2007 AND
          月=10
    B、 不要对索引字段进行格式转换
    日期字段的例子:
    WHERE CONVERT(VARCHAR(10), 日期字段,120)=’2008-08-15’
    应该改为
    WHERE日期字段〉=’2008-08-15’         AND   日期字段<’2008-08-16’
    ISNULL转换的例子:
    WHERE ISNULL(字段,’’)<>’’应改为:WHERE字段<>’’
    WHERE ISNULL(字段,’’)=’’不应修改
    WHERE ISNULL(字段,’F’) =’T’应改为: WHERE字段=’T’
    WHERE ISNULL(字段,’F’)<>’T’不应修改
    C、 不要对索引字段使用函数
    WHERE LEFT(NAME, 3)='ABC' 或者WHERE SUBSTRING(NAME,1, 3)='ABC'
    应改为:
    WHERE NAME LIKE 'ABC%'
    日期查询的例子:
    WHERE DATEDIFF(DAY, 日期,'2005-11-30')=0应改为:WHERE 日期 >='2005-11-30' AND 日期 <'2005-12-1‘
    WHERE DATEDIFF(DAY, 日期,'2005-11-30')>0应改为:WHERE 日期 <'2005-11-30‘
    WHERE DATEDIFF(DAY, 日期,'2005-11-30')>=0应改为:WHERE 日期 <'2005-12-01‘
    WHERE DATEDIFF(DAY, 日期,'2005-11-30')<0应改为:WHERE 日期>='2005-12-01‘
    WHERE DATEDIFF(DAY, 日期,'2005-11-30')<=0应改为:WHERE 日期>='2005-11-30‘
    D、不要对索引字段进行多字段连接
    比如:
    WHERE FAME+ ’.’+LNAME=‘HAIWEI.YANG’
    应改为:
    WHERE FNAME=‘HAIWEI’ AND LNAME=‘YANG’

    8、 注意连接条件的写法
    多表连接的连接条件对索引的选择有着重要的意义,所以我们在写连接条件条件的时候需要特别的注意。
    A、多表连接的时候,连接条件必须写全,宁可重复,不要缺漏。
    B、 连接条件尽量使用聚集索引
    C、 注意ON部分条件和WHERE部分条件的区别

    9、 其他需要注意的地方
    经验表明,问题发现的越早解决的成本越低,很多性能问题可以在编码阶段就发现,为了提早发现性能问题,需要注意:
    A、程序员注意、关心各表的数据量。
    B、编码过程和单元测试过程尽量用数据量较大的数据库测试,最好能用实际数据测试。
    C、每个SQL语句尽量简单
    D、不要频繁更新有触发器的表的数据
    E、注意数据库函数的限制以及其性能

    10、学会分辩SQL语句的优劣
    自己分辨SQL语句的优劣非常重要,只有自己能分辨优劣才能写出高效的语句。
    A、看SQL语句的执行计划,可以在查询分析其使用CTRL+L图形化的显示执行计划,一般应该注意百分比最大的几个图形的属性,把鼠标移动到其上面会显示这个图形的属性,需要注意预计成本的数据,也要注意其标题,一般都是CLUSTERED INDEX SEEK 、INDEX SEEK 、CLUSTERED INDEX SCAN 、INDEX SCAN 、TABLE SCAN等,其中出现SCAN说明语句有油画的余地。也可以用语句
    SET SHOWPLAN_ALL ON
    要执行的语句
    SET SHOWPLAN_ALL OFF
    查看执行计划的文本详细信息。
    B、用事件探查器跟踪系统的运行,可疑跟踪到执行的语句,以及所用的时间,CPU用量以及I/O数据,从而分析语句的效率。
    C、可以用WINDOWS的系统性能检测器,关注CPU、I/O参数

  • SQL中的聚集索引和非聚集索引的区别

    2008-11-07 11:57:10

    (1)聚集索引:表中存储的数据按照索引的顺序存储,检索效率比普通索引高,但对数据新增/修改/删除的影响比较大
    特点:
      (1) 一个表可以最多可以创建249个索引
      (2) 先建聚集索引才能创建非聚集索引
       (3) 非聚集索引数据与索引不同序
       (4) 数据与索引在不同位置
       (5) 索引在叶节点上存储,在叶节点上有一个"指针"直接指向要查询的数据区域
       (6) 数据不会根据索引键的顺序重新排列数据

    创建聚集索引的语法:
      create NONCLUSTERED INDEX idximpID ON EMP(empID)

    (2)非聚集索引:不影响表中的数据存储顺序,检索效率比聚集索引低,对数据新增/修改/删除的影响很少
    特点:
      (1) 无索引,数据无序
      (2) 有索引,数据与索引同序
      (3) 数据会根据索引键的顺序重新排列数据
      (4) 一个表只能有一个索引
      (5) 叶节点的指针指向的数据也在同一位置存储

    语法:
    create CLUSTERED INDEX idxempID on emp(empID)

    (3)惟一索引:惟一索引可以确保索引列不包含重复的值.
    可以用多个列,但是索引可以确保索引列中每个值组合都是唯一的
    姓  名
    李  二
    张  三
    王  五
    语法: create unique index idxempid on emp(姓,名)

    (4)复合索引:如果在两上以上的列上创建一个索引,则称为复合索引。
    那么,不可能有两行的姓和名是重复的
    语法:
    create index indxfullname on addressbook(firstname,lastname)

    (5)系统自建的索引:在使用T_sql语句创建表的时候使用PRIMARY KEY或UNIQUE约束时,会在表上自动创建一个惟一索引
    自动创建的索引是无法删除的
    语法:
    create table ABc
    ( empID int primary key,
      firstname varchar(50)UNIQUE,
      lastname  varchar(50)UNIQUE,
    )
    这样的结果就出来了三个索引,但只有一个聚集索引哦

  • SQL中的N

    2008-11-07 10:49:49

    在SQL中看到这样一个语句
    SELECT COUNT(*)
    FROM msdb.dbo.syscategories
    WHERE name = N'[Uncategorized (Local)]'

    请注意在name=后面有个N, 请问这个 N 起什么作用?

    加上 N 代表存入数据库时以 Unicode 格式存储。
    N'string' 表示string是个Unicode字符串

    Unicode 字符串的格式与普通字符串相似,但它前面有一个 N 标识符(N 代表 SQL-92 标准中的国际语言 (National Language))。N 前缀必须是大写字母。例如,'Michél' 是字符串常量而 N'Michél' 则是 Unicode 常量。Unicode 常量被解释为 Unicode 数据,并且不使用代码页进行计算。Unicode 常量确实有排序规则,主要用于控制比较和区分大小写。为 Unicode 常量指派当前数据库的默认排序规则,除非使用 COLLATE 子句为其指定了排序规则。Unicode 数据中的每个字符都使用两个字节进行存储,而字符数据中的每个字符则都使用一个字节进行存储。有关更多信息,请参见使用 Unicode 数据。

  • 查询锁的表含义(sp_lock)

    2008-11-05 17:06:47

    SP_LOCK

    其显示信息为:

    Spid:进程ID号(要发现哪些用户和该spid相连,你就要执行存储过程sp_who)

    Dbid:数据库ID号(可以在主数据库中的sysdatabases表格中找到它)

    Objid:对象ID号(要查看这个对象,你可以在主数据库中的sysobjects表格中查询指定的objid)

    Indid:索引ID

    Type:缩写的对象类型(DB:数据库、TAB:表、PG:页、EXT:簇、RID:行标等)

    Resource:锁资源

    Mode:锁模式(S:共享锁、U:修改锁、X:排它锁、IS共享意图锁、IX排它意图锁)

    Status:当前该锁的状态(GRANT获得状态、WAIT被其它进程阻塞、CVNT当前锁正在转化)

    当你发现一个spid 获得了大量的数据库锁定时,这将有助于确定什么存储过程或语句正在运行。为了达到这个目的,运行以下 DBCC 命令: 

      DBCC INPUTBUFFER(spid) 

      这个DBCC命令将返回正在EventInfo字段中运行的语句的相关信息。

    类型列  
      "类型"列显示当前锁定的资源类型。  
       
      资源类型   描述    
      RID   用于锁定表中的一行的行标识符。    
      KEY   索引中的行锁。用于保护可串行事务中的键范围。    
      PAG   数据或索引页。    
      EXT   相邻的八个数据页或索引页构成的一组。    
      TAB   包括所有数据和索引在内的整个表。    
      DB   数据库。    
       
       
      资源列  
      "资源"列提供有关正被锁定资源的信息。  
       
      资源类型   描述    
      RID   表内已锁定行的行标识符。行由   fileid:page:rid   组合进行标识,其中,rid   是页中的行标识符。    
      KEY   SQL   Server   内部使用的十六进制数字。    
      PAG   页码。页由   fileid:page   组合进行标识,其中,fileid   是   sysfiles   表中的   fileid,而   page   是该文件内的逻辑页码。    
      EXT   正被锁定的扩展盘区中的第一个页码。页由   fileid:page   组合进行标识。    
      TAB   由于   ObjId   列已包含表的对象   ID,所以没有提供任何信息。    
      DB   由于   dbid   列已包含数据库的数据库   ID,所以没有提供任何信息。    
       
       
      在sp_lock的结果集内,锁定的RID资源类型中的资源描述为1:1225:2。这表明在fileid1内、页码为1225的页中、行标识符为2的行上应用了锁。有关更多信息,请参见有关死锁的疑难解答。  
       
      模式列  
      "模式"列描述正应用于资源的锁类型。锁类型包括任何多粒锁。  
       
      状态列  
      "状态"列显示锁是已经获取(GRANT)、正在另一个进程中被阻塞(WAIT)、还是正在转换为另一个锁(CNVT)。正转换为另一种锁的锁会保持在一种模式中,但等待获取更强的锁模式(例如,从更新模式变为排它模式)。当遇到诊断阻塞问题时,会认为CNVT与WAIT类似。  
       
      监视锁定活动的其它工具  
      当持有和释放锁的速度比sp_lock显示的速度快时,使用sp_lock来显示锁定信息并不一定始终可行。在这种情况下,可以使用SQL事件探查器监视和记录锁定信息。此外,可以使用Windows性能监视器监视使用SQL Server锁对象计数器的锁活动。

       
    (1)共享   (S)   用于不更改或不更新数据的操作(只读操作),如   SELECT   语句。    
    (2)更新   (U)   用于可更新的资源中。防止当多个会话在读取、锁定以及随后可能进行的资源更新时发生常见形式的死锁。     
    (3)排它   (X)   用于数据修改操作,例如   INSERT、UPDATE   或   DELETE。确保不会同时对同一资源进行多重更新。    
    (4)意向   用于建立锁的层次结构。意向锁的类型为:意向共享   (IS)、意向排它   (IX)   以及与意向排它共享   (SIX)。    
    (5)架构   在执行依赖于表架构的操作时使用。架构锁的类型为:架构修改   (Sch-M)   和架构稳定性   (Sch-S)。    
    (6)大容量更新   (BU)   向表中大容量复制数据并指定了   TABLOCK   提示时使用。

     

231/212>
Open Toolbar