分类目录归档:数据库

数据库入门与提高::::::演道网数据库专栏提供一线数据库研发人员在学习工作中的经验,减少大家走的弯路,大量源码可以直接使用。

mysql忘记root密码办?

首先停止数据库

如果是利用apt-get或yum安装的mysql可以直接执行mysql.server stop命令
如果数据库为编译安装,那么需要进入到mysql的命令目录bin/下,
执行:./mysql.server stop
centos试试

 service mysqld stop

修改my.cnf

利用vim命令打开mysql配置文件my.cnf

在mysqld进程配置文件中添加skip-grant-tables,添加完成后,执行wd保存。

重启数据库

利用命令行工具重启数据库

./mysql.server start(centos试试 service mysqld start)

修改root密码

重启数据库后可以不用密码直接登陆,执行:

./mysql -p

可以直接登陆进数据库。

在mysql命令行下执行以下命令修改root密码:

update mysql.user  set password=password('newpassword') where user='root'

#将password()中的newpassword字符更改为你自己的密码

重启数据库

密码修改完成后,将my.cnf文件中添加的skip-grant-tables语句注释或删除掉,然后重启数据库即可

centos试试 service mysqld restart

登陆检测

可以使用新密码重新登陆测试

END

[MySQL]查看用户权限与GRANT用法

先提示,本文需要一定的python源码基础。许多内容请参考《python源码剖析》。下面切入正题。

 

今天在群里有人问了一个问题。形如如下的一段程序。

 

Python代码

  1.      
  2. class person:  
  3.     sum = 0  
  4.     def __init__(self,name):  
  5.         self.name=name  
  6.         person.sum += 1  
  7.   
  8.     def __del__(self):  
  9.         person.sum -= 1  
  10.         print “%s is leaving” % self.name  
  11.   
  12. a = person(‘a’)  
  13. a2 = person(‘a2’)  

class person: sum = 0 def __init__(self,name): self.name=name person.sum += 1 def __del__(self): person.sum -= 1 print “%s is leaving” % self.name a = person(‘a’) a2 = person(‘a2’)

 

这段程序的预期的执行结果应该是”a is leaving”和”a2 is leaving”。但是实际上却出乎意料之外,实际的执行结果如下:

 

Python代码

  1. a is leaving  
  2. Exception exceptions.AttributeError: “‘NoneType’ object has no attribute ‘sum'” in   
  3. > ignored  

a is leaving Exception exceptions.AttributeError: “‘NoneType’ object has no attribute ‘sum'” in > ignored

为什么引用的名字不同造成的结果会有这么大的差别呢?

 

分析表面的原因,是person这个引用被指向了None。那他是不是真的是None呢?

 

Python代码

  1. def __del__(self):  
  2.     print globals()[‘person’] #1  
  3.     person.sum -= 1  
  4.     #print “%s is leaving” % self.name  

def __del__(self): print globals()[‘person’] #1 person.sum -= 1 #print “%s is leaving” % self.name

 

加入红色这行代码,看看是不是真的变成了None。运行结果如下:

 

Java代码

  1. __main__.person  
  2. None  
  3. Exception exceptions.AttributeError: “‘NoneType’ object has no attribute ‘sum'”  
  4.  in > ignored  

__main__.person None Exception exceptions.AttributeError: “‘NoneType’ object has no attribute ‘sum'” in > ignored

看来是真的变成了None了。

 

初步分析原因,应该是程序在执行结束以后,python虚拟机清理环境的时候将”person”这个符号先于”a2″清理了,所以导致在a2的析构函数中无法找到”person”这个符号了。

 

但是转念一想还是不对,如果是”person”符号找不到了,应该是提示“name ‘person’ is not defined”才对。说明”person”这个符号还在,那”person”指向的class_object对象还在吗?改变程序为以下格式:

 

Python代码

  1. class person:  
  2.     sum = 0  
  3.     def __init__(self,name):  
  4.         self.name=name  
  5.         person.sum += 1  
  6.   
  7.     def __del__(self):  
  8.         #person.sum -= 1  
  9.         self.__class__.sum -= 1 #1  
  10.         #print “%s is leaving” % self.name  
  11.   
  12. a = person(‘a’)  
  13. a2 = person(‘a2’)  

class person: sum = 0 def __init__(self,name): self.name=name person.sum += 1 def __del__(self): #person.sum -= 1 self.__class__.sum -= 1 #1 #print “%s is leaving” % self.name a = person(‘a’) a2 = person(‘a2’)

红色代码就是修改部分,利用自身的__class__来操作。运行结果一切正常。

 

说明python虚拟机在回收的过程中,只是将”person”这个符号设置成None了。这个结论同时带来2个问题:第一,为什么会设置成None?第二:为什么”person”会先于”a2″而晚于”a”被回收?

 

先来分析第二个问题。第一反应是不是按照字母的顺序来回收?但是马上这个结论被推翻。”a”和”a2″都在”person”的前面。那么难道是根据globals()这个字典的key顺序来回收?执行一下globals().keys()方法,得到以下结果:

 

Python代码

  1. [‘a’, ‘__builtins__’, ‘__file__’, ‘person’, ‘a2’, ‘__name__’, ‘__doc__’]   

[‘a’, ‘__builtins__’, ‘__file__’, ‘person’, ‘a2’, ‘__name__’, ‘__doc__’] 

 

看来的确是这样。

 

但是为什么是这样?要得出这个结论,看来只有去python源码中找答案了。

 

大家都知道,python代码在运行的时候,会存在一个frameobject对象来表示运行时的环境。类似于c语言的栈帧,也有点像lisp的函数的生存空间,看起来答案要从frameobject.c这个文件中去找了。

 

在frameobject.c中发现了一个函数:static void frame_dealloc(PyFrameObject *f)。看来解决问题的关键就在眼前。

 

在frame_dealloc里面截取了以下一段代码:

 

Python代码

  1. Py_XDECREF(f->f_back);  
  2. Py_DECREF(f->f_builtins);  
  3. Py_DECREF(f->f_globals);  
  4. Py_CLEAR(f->f_locals);  
  5. Py_CLEAR(f->f_trace);  
  6. Py_CLEAR(f->f_exc_type);  
  7. Py_CLEAR(f->f_exc_value);  
  8. Py_CLEAR(f->f_exc_traceback);  

Py_XDECREF(f->f_back); Py_DECREF(f->f_builtins); Py_DECREF(f->f_globals); Py_CLEAR(f->f_locals); Py_CLEAR(f->f_trace); Py_CLEAR(f->f_exc_type); Py_CLEAR(f->f_exc_value); Py_CLEAR(f->f_exc_traceback);

原来减少了引用啊。。关于Py_DECREF这个宏,python源码里面的解释是这样的:

 

The macros Py_INCREF(op) and Py_DECREF(op) are used to increment or decrement
reference counts. Py_DECREF calls the object’s deallocator function when
the refcount falls to 0;

 

这么说来,我们就要去找f_globals的析构函数了。f_globals是个什么呢?当然是PyDictObject了。证据么遍地都是啊,比 如随手找了一个,在PyFrameObject * PyFrame_New(PyThreadState *tstate, PyCodeObject *code, PyObject *globals,PyObject *locals)这个函数里面有一段代码:

 

Python代码

  1. #ifdef Py_DEBUG  
  2.     if (code == NULL || globals == NULL || !PyDict_Check(globals) ||  
  3.         (locals != NULL && !PyMapping_Check(locals))) {  
  4.         PyErr_BadInternalCall();  
  5.         return NULL;  
  6.     }  
  7. #endif  

#ifdef Py_DEBUG if (code == NULL || globals == NULL || !PyDict_Check(globals) || (locals != NULL && !PyMapping_Check(locals))) { PyErr_BadInternalCall(); return NULL; } #endif

PyDict_Check。。。检查是否是Dict对象。好吧,此处略过,直接奔向dictobject.c看看里面的代码。

 

C代码

  1. static void  
  2. dict_dealloc(register dictobject *mp)  
  3. {  
  4.     register dictentry *ep;  
  5.     Py_ssize_t fill = mp->ma_fill;  
  6.     PyObject_GC_UnTrack(mp);  
  7.     Py_TRASHCAN_SAFE_BEGIN(mp)  
  8.     for (ep = mp->ma_table; fill > 0; ep++) {  
  9.         if (ep->me_key) {  
  10.             –fill;  
  11.             Py_DECREF(ep->me_key);  #  
  12.             Py_XDECREF(ep->me_value); #仅仅只是引用计数减一  
  13.         }  
  14.     }  
  15. 以下略  

static void dict_dealloc(register dictobject *mp) { register dictentry *ep; Py_ssize_t fill = mp->ma_fill; PyObject_GC_UnTrack(mp); Py_TRASHCAN_SAFE_BEGIN(mp) for (ep = mp->ma_table; fill > 0; ep++) { if (ep->me_key) { –fill; Py_DECREF(ep->me_key); # Py_XDECREF(ep->me_value); #仅仅只是引用计数减一 } } 以下略

哈哈哈。还真是按照key的顺序来一个一个清除的。

 

不过,怎么又回到了Py_DECREF啊?

 

看来最终解释这个问题要回到GC上面了。

 

其实从这个地方也可以看出第一个问题的答案了,为什么是None?

 

从上面代码可以看出,dictobject对象在析构的时候,仅仅只是将value的引用计数减一,至于这个对象什么时候被真正回收,其实是由GC决定而不确定的。也就是说为什么是None,是因为减一了以后,凑巧GC到了而已。

 

根据Python本身的文档。

 

Python 写道Warning: Due to the precarious circumstances under which __del__() methods are invoked, exceptions that occur during their execution are ignored, and a warning is printed to sys.stderr instead. Also, when __del__() is invoked in response to a module being deleted (e.g., when execution of the program is done), other globals referenced by the __del__() method may already have been deleted. For this reason, __del__() methods should do the absolute minimum needed to maintain external invariants. Starting with version 1.5, Python guarantees that globals whose name begins with a single underscore are deleted from their module before other globals are deleted; if no other references to such globals exist, this may help in assuring that imported modules are still available at the time when the __del__() method is called.

Python不能保证__del__被调用的时候所有的引用都有,所以,尽量不要overried类的__del__方法。

 

到此结束。

mysql show status

mysql(SHOW STATUS)性能的检查和调优方法

记录慢查询:
在my.cnf中配置
[mysqld]
; enable the slow query log, default 10 seconds
log-slow-queries
; log queries taking longer than 5 seconds
long_query_time = 5
; log queries that don’t use indexes even if they take less than long_query_time
; MySQL 4.1 and newer only
log-queries-not-using-indexes

慢速查询日志都保存在 MySQL 数据目录中,名为 hostname-slow.log。如果希望使用一个不同的名字或路径,可以在 my.cnf 中使用 log-slow-queries = /new/path/to/file 实现此目的。
阅读慢速查询日志最好是通过 mysqldumpslow 命令进行。指定日志文件的路径,就可以看到一个慢速查询的排序后的列表,并且还显示了它们在日志文件中出现的次数。一个非常有用的特性是 mysqldumpslow 在比较结果之前,会删除任何用户指定的数据,因此对同一个查询的不同调用被计为一次;这可以帮助找出需要工作量最多的查询。

对查询进行缓存:
默认不启用
启用方法 将 query_cache_size = 32M 添加到 /etc/my.conf 中可以启用 32MB 的查询缓存。

监视查询缓存的统计信息
mysql> SHOW STATUS LIKE ‘qcache%’;
+————————-+————+
| Variable_name | Value |
+————————-+————+
| Qcache_free_blocks | 5216 |
| Qcache_free_memory | 14640664 |
| Qcache_hits | 2581646882 |
| Qcache_inserts | 360210964 |
| Qcache_lowmem_prunes | 281680433 |
| Qcache_not_cached | 79740667 |
| Qcache_queries_in_cache | 16927 |
| Qcache_total_blocks | 47042 |
+————————-+————+
8 rows in set (0.00 sec)

Qcache_free_blocks 缓存中相邻内存块的个数。数目大说明可能有碎片。FLUSH QUERY CACHE 会对缓存中的碎片进行整理,从而得到一个空闲块。
Qcache_free_memory 缓存中的空闲内存。
Qcache_hits 每次查询在缓存中命中时就增大。
Qcache_inserts 每次插入一个查询时就增大。命中次数除以插入次数就是不中比率;用 1 减去这个值就是命中率。在上面这个例子中,大约有 87% 的查询都在缓存中命中。
Qcache_lowmem_prunes 缓存出现内存不足并且必须要进行清理以便为更多查询提供空间的次数。这个数字最好长时间来看;如果这个数字在不断增长,就表示可能碎片非常严重,或者内存 很少。(上面的 free_blocks 和 free_memory 可以告诉您属于哪种情况)。
Qcache_not_cached 不适合进行缓存的查询的数量,通常是由于这些查询不是 SELECT 语句。
Qcache_queries_in_cache 当前缓存的查询(和响应)的数量。
Qcache_total_blocks 缓存中块的数量。

强制限制:
在my.cnf中设置
set-variable=max_connections=500
set-variable=wait_timeout=10 #终止空闲超过10秒的连接
max_connect_errors = 100 #主机连接到mysql 100次无法建立连接,就锁定直到flush hosts 之后.

查看当前最大连接数
mysql> show status like ‘max_used_connections’;

缓冲区和缓存:
设置打开文件缓存
/etc/mysqld.conf
table_cache=5000

显示打开表的活动
mysql> SHOW STATUS LIKE ‘open%tables’;
+—————+——-+
| Variable_name | Value |
+—————+——-+
| Open_tables | 5000 |
| Opened_tables | 195 |
+—————+——-+
2 rows in set (0.00 sec)
如果 Open_tables 比 table_cache 设置小很多,就说明该值太大了.

设置线程缓存
在 my.cnf中
thread_cache = 40
显示线程使用统计信息
mysql> SHOW STATUS LIKE ‘threads%’;
+——————-+——–+
| Variable_name | Value |
+——————-+——–+
| Threads_cached | 27 |
| Threads_connected | 15 |
| Threads_created | 838610 |
| Threads_running | 3 |
+——————-+——–+
4 rows in set (0.00 sec)

如果连续执行show status命令 Threads_created 都快速增加 就应该增加线程缓存.

设置关键字缓存
key_buffer = 384M
确定关键字效率
mysql> show status like ‘%key_read%’;
+——————-+———–+
| Variable_name | Value |
+——————-+———–+
| Key_read_requests | 163554268 |
| Key_reads | 98247 |
+——————-+———–+
2 rows in set (0.00 sec)

key_reads 命中磁盘的请求个数
key_read_requests 是请求总数
如果1000个请求中有超过1个命中磁盘,就应该考虑增大关键字缓存.

设置临时表
临时表太大就会写入磁盘
在my.cnf中设置
tmp_table_size
max_heap_table_size
显示临时表
mysql> SHOW STATUS LIKE ‘created_tmp%’;
+————————-+——-+
| Variable_name | Value |
+————————-+——-+
| Created_tmp_disk_tables | 30660 |
| Created_tmp_files | 2 |
| Created_tmp_tables | 32912 |
+————————-+——-+
3 rows in set (0.00 sec)

设置每个会话
my.cnf中修改 或通过代码修改
sort_buffer_size = 4M 将排序缓冲区设置为 4MB
mysql> SHOW STATUS LIKE “sort%”;
+——————-+———+
| Variable_name | Value |
+——————-+———+
| Sort_merge_passes | 1 |
| Sort_range | 79192 |
| Sort_rows | 2066532 |
| Sort_scan | 44006 |
+——————-+———+
4 rows in set (0.00 sec)
如果 sort_merge_passes 很大,就表示需要注意 sort_buffer_size

确定表的扫描比率
mysql> SHOW STATUS LIKE “com_select”;
+—————+——–+
| Variable_name | Value |
+—————+——–+
| Com_select | 318243 |
+—————+——–+
1 row in set (0.00 sec)

mysql> SHOW STATUS LIKE “handler_read_rnd_next”;
+———————–+———–+
| Variable_name | Value |
+———————–+———–+
| Handler_read_rnd_next | 165959471 |
+———————–+———–+
1 row in set (0.00 sec)

Handler_read_rnd_next / Com_select 得出了表扫描比率 —— 在本例中是 521:1。如果该值超过 4000,就应该查看 read_buffer_size,例如 read_buffer_size = 4M。如果这个数字超过了 8M,就应该与开发人员讨论一下对这些查询进行调优了!

3个工具
mytop
mysqlard
mysqlreport

flush show

函数介绍
benchmark

key_reads/Key_read_requests<0.01 OK
key_writes/Key_write_requests<1 OK

Optimize table table_name
对表自动优化

Explain select statement

Flush flush_option [Privileges,tables,hosts,logs]

优化mysql in () order by

mysql(SHOW STATUS)性能的检查和调优方法

记录慢查询:
在my.cnf中配置
[mysqld]
; enable the slow query log, default 10 seconds
log-slow-queries
; log queries taking longer than 5 seconds
long_query_time = 5
; log queries that don’t use indexes even if they take less than long_query_time
; MySQL 4.1 and newer only
log-queries-not-using-indexes

慢速查询日志都保存在 MySQL 数据目录中,名为 hostname-slow.log。如果希望使用一个不同的名字或路径,可以在 my.cnf 中使用 log-slow-queries = /new/path/to/file 实现此目的。
阅读慢速查询日志最好是通过 mysqldumpslow 命令进行。指定日志文件的路径,就可以看到一个慢速查询的排序后的列表,并且还显示了它们在日志文件中出现的次数。一个非常有用的特性是 mysqldumpslow 在比较结果之前,会删除任何用户指定的数据,因此对同一个查询的不同调用被计为一次;这可以帮助找出需要工作量最多的查询。

对查询进行缓存:
默认不启用
启用方法 将 query_cache_size = 32M 添加到 /etc/my.conf 中可以启用 32MB 的查询缓存。

监视查询缓存的统计信息
mysql> SHOW STATUS LIKE ‘qcache%’;
+————————-+————+
| Variable_name | Value |
+————————-+————+
| Qcache_free_blocks | 5216 |
| Qcache_free_memory | 14640664 |
| Qcache_hits | 2581646882 |
| Qcache_inserts | 360210964 |
| Qcache_lowmem_prunes | 281680433 |
| Qcache_not_cached | 79740667 |
| Qcache_queries_in_cache | 16927 |
| Qcache_total_blocks | 47042 |
+————————-+————+
8 rows in set (0.00 sec)

Qcache_free_blocks 缓存中相邻内存块的个数。数目大说明可能有碎片。FLUSH QUERY CACHE 会对缓存中的碎片进行整理,从而得到一个空闲块。
Qcache_free_memory 缓存中的空闲内存。
Qcache_hits 每次查询在缓存中命中时就增大。
Qcache_inserts 每次插入一个查询时就增大。命中次数除以插入次数就是不中比率;用 1 减去这个值就是命中率。在上面这个例子中,大约有 87% 的查询都在缓存中命中。
Qcache_lowmem_prunes 缓存出现内存不足并且必须要进行清理以便为更多查询提供空间的次数。这个数字最好长时间来看;如果这个数字在不断增长,就表示可能碎片非常严重,或者内存 很少。(上面的 free_blocks 和 free_memory 可以告诉您属于哪种情况)。
Qcache_not_cached 不适合进行缓存的查询的数量,通常是由于这些查询不是 SELECT 语句。
Qcache_queries_in_cache 当前缓存的查询(和响应)的数量。
Qcache_total_blocks 缓存中块的数量。

强制限制:
在my.cnf中设置
set-variable=max_connections=500
set-variable=wait_timeout=10 #终止空闲超过10秒的连接
max_connect_errors = 100 #主机连接到mysql 100次无法建立连接,就锁定直到flush hosts 之后.

查看当前最大连接数
mysql> show status like ‘max_used_connections’;

缓冲区和缓存:
设置打开文件缓存
/etc/mysqld.conf
table_cache=5000

显示打开表的活动
mysql> SHOW STATUS LIKE ‘open%tables’;
+—————+——-+
| Variable_name | Value |
+—————+——-+
| Open_tables | 5000 |
| Opened_tables | 195 |
+—————+——-+
2 rows in set (0.00 sec)
如果 Open_tables 比 table_cache 设置小很多,就说明该值太大了.

设置线程缓存
在 my.cnf中
thread_cache = 40
显示线程使用统计信息
mysql> SHOW STATUS LIKE ‘threads%’;
+——————-+——–+
| Variable_name | Value |
+——————-+——–+
| Threads_cached | 27 |
| Threads_connected | 15 |
| Threads_created | 838610 |
| Threads_running | 3 |
+——————-+——–+
4 rows in set (0.00 sec)

如果连续执行show status命令 Threads_created 都快速增加 就应该增加线程缓存.

设置关键字缓存
key_buffer = 384M
确定关键字效率
mysql> show status like ‘%key_read%’;
+——————-+———–+
| Variable_name | Value |
+——————-+———–+
| Key_read_requests | 163554268 |
| Key_reads | 98247 |
+——————-+———–+
2 rows in set (0.00 sec)

key_reads 命中磁盘的请求个数
key_read_requests 是请求总数
如果1000个请求中有超过1个命中磁盘,就应该考虑增大关键字缓存.

设置临时表
临时表太大就会写入磁盘
在my.cnf中设置
tmp_table_size
max_heap_table_size
显示临时表
mysql> SHOW STATUS LIKE ‘created_tmp%’;
+————————-+——-+
| Variable_name | Value |
+————————-+——-+
| Created_tmp_disk_tables | 30660 |
| Created_tmp_files | 2 |
| Created_tmp_tables | 32912 |
+————————-+——-+
3 rows in set (0.00 sec)

设置每个会话
my.cnf中修改 或通过代码修改
sort_buffer_size = 4M 将排序缓冲区设置为 4MB
mysql> SHOW STATUS LIKE “sort%”;
+——————-+———+
| Variable_name | Value |
+——————-+———+
| Sort_merge_passes | 1 |
| Sort_range | 79192 |
| Sort_rows | 2066532 |
| Sort_scan | 44006 |
+——————-+———+
4 rows in set (0.00 sec)
如果 sort_merge_passes 很大,就表示需要注意 sort_buffer_size

确定表的扫描比率
mysql> SHOW STATUS LIKE “com_select”;
+—————+——–+
| Variable_name | Value |
+—————+——–+
| Com_select | 318243 |
+—————+——–+
1 row in set (0.00 sec)

mysql> SHOW STATUS LIKE “handler_read_rnd_next”;
+———————–+———–+
| Variable_name | Value |
+———————–+———–+
| Handler_read_rnd_next | 165959471 |
+———————–+———–+
1 row in set (0.00 sec)

Handler_read_rnd_next / Com_select 得出了表扫描比率 —— 在本例中是 521:1。如果该值超过 4000,就应该查看 read_buffer_size,例如 read_buffer_size = 4M。如果这个数字超过了 8M,就应该与开发人员讨论一下对这些查询进行调优了!

3个工具
mytop
mysqlard
mysqlreport

flush show

函数介绍
benchmark

key_reads/Key_read_requests<0.01 OK
key_writes/Key_write_requests<1 OK

Optimize table table_name
对表自动优化

Explain select statement

Flush flush_option [Privileges,tables,hosts,logs]

mysql show指令

问题 浏览器 DEMO 解决方法 Hacking Rules:

property:all-ie\9; property:gte-ie8\0;*property:lte-ie7; +property:ie7; _property:ie6;

1 input[button | submit] 不能用 margin:0 auto; 居中 IE8 bug | fixed 为input添加width 2 body{overflow:hidden;}没有去掉滚动条 IE6/7 bug | fixed 设置html{overflow:hidden;} 3 hasLayout的标签拥有高度 IE6/7 bug | fixed *height:0;
_overflow:hidden; 4 form>[hasLayout]元素有margin-left时,子元素中的[input | textarea] 出现2×margin-left IE6/7 bug | fixed form > [hasLayout 元素]{margin-left:宽度;}
form div{*margin-left:宽度÷2;} 5 当border-width有1条<边3条时被设置成dotted时,1px的边dotted显示成dashed IE7 bug | fixed 不在同一个元素上使用不同宽度的 dotted 6 当子元素有position:relative的时候,父元素设置overflow:[hidden|auto]相当于给子元素设置了position:visible; IE6/7 bug | fixed 给父元素设置position:relative; 7 :hover伪类不能改变有position:absolute的子级元素的left/top值 IE7 bug | fixed 把top/left的值设置成除0%外的所有百分值;或添加一个margin-[所有方向]除0外的所有值,包括0% 8 :focus + selector {} 选择器失效 IE8 bug | fixed 在失效选择器后面添加一个空选择器, :focus{} 9 列表中混乱的浮动:在list中浮动图片时,图片出现溢出正常位置;或没有list-style IE8 bug | fixed 用背景图片替换list-style 10 th 不会自动继承上级元素的 text-align IE8 bug | fixed 给th添加text-align:inherit; 11 样式(包括link/style/@import(link)) 最多允许个为是:32 IE6-8 ─ 常识 99.99%的情况下,不会遇到 12 :hover 时若background-color为#fff, 失效 IE7 bug | fixed 把background-color改成background。或者,非#fff || #ffffff 13 忽略’>’后有注释的选择器:selector> /**/ selector{} IE7 bug | fixed 官方DEMO有误 14 * html IE6 ─ HACK 只对IE6有效 15 PNG图片中的颜色和背景颜色的值相同,但显示不同 IE6-7 bug | fixed 利用 pngcrush 去除图片中的 Gamma profiles 16 margin:0 auto; 不能让block元素水平居中 IE6-8 bug | fixed 给block元素添加一个width 17 使用伪类 :first-line | :first-letter, 属性的值中出现!important 会使属性失效 IE8 bug | fixed !important is evil, don’t use it anymore 18 :first-letter 失效 IE6 bug | fixed 把 :first-letter 移到离{}最近的地方,如 h1, p:first-letter{},而非 p:first-letter h1{} 19 Position:absolute元素中,a display:block, 在非:hover时只有文本可点击 IE6/7 bug | fixed 给a添加background, 如果背景透明,使用background:url(‘任何页面中已经缓存的文件链接’),不推荐background:url(#)[官方的解决方法],因为会增加一下HTTP请求 20 float列表元素不水平对齐:li不设置float,a设置display:block;float:[方向],li不水平对齐 IE6/7 bug | fixed 给li设置display:inline 或 float:[方向] 21 dt, dd, li 背景失效 IE6 bug | fixed dt, dd, li{position:relative;} 22

memcache协议(一)

取回命令一行取回命令如下:get *\r\n- * 表示一个或多个键值,由空格隔开的字串.这行命令以后,客户端的等待0个或多个项目,每项都会收到一行文本,然后跟着数据区块。所有项目传送完毕后,服务器发送以下字串:
“END\r\n”来指示回应完毕。服务器用以下形式发送每项内容:VALUE \r\n
\r\n- 是所发送的键名- 是存储命令所设置的记号

是随后数据块的长度,*不包括* 它的界定符“\r\n”- 是发送的数据如果在取回请求中发送了一些键名,而服务器没有送回项目列表,这意味着服务器没这些键名(可能因为它们从未被存储,或者为给其他内容腾出空间而被删除,或者到期,或者被已客户端删除)。删除Deletion命令“delete”允许从外部删除内容:delete

是客户端要增加/减少的总数。回复为以下集中情形:

– “NOT_FOUND\r\n”指示该项内容的值,不存在。- \r\n ,是 增加/减少 。
注意”decr”命令发生下溢:如果客户端尝试减少的结果小于0时,结果会是0。”incr” 命令不会发生溢出。状态
命令”stats” 被用于查询服务器的运行状态和其他内部数据。有两种格式。不带参数的:
stats\r\n这会在随后输出各项状态、设定值和文档。另一种格式带有一些参数:
stats \r\n通过,服务器传回各种内部数据。因为随时可能发生变动,本文不提供参数的种类及其传回数据。各种状态受到无参数的”stats”命令后,服务器发送多行内容,如下:STAT \r\n服务器用以下一行来终止这个清单:END\r\n在每行状态中, 是状态的名字, 使状态的数据。 以下清单,是所有的状态名称,数据类型,和数据代表的含义。
在“类型”一列中,”32u”表示32位无符号整型,”64u”表示64位无符号整型,”32u:32u”表示用冒号隔开的两个32位无符号整型。 名称/Name 类型/Type 含义/Meaning pid 32u 服务器进程ID Process id of this server process uptime 32u 服务器运行时间,单位秒 Number of seconds this server has been running time 32u 服务器当前的UNIX时间 current UNIX time according to the server version string 服务器的版本号 Version string of this server rusage_user 32u:32u 该进程累计的用户时间
(秒:微妙) Accumulated user time for this process 
(seconds:microseconds) rusage_system 32u:32u 该进程累计的系统时间 
(秒:微妙) Accumulated system time for this process 
(seconds:microseconds) curr_items 32u 服务器当前存储的内容数量 Current number of items stored by the server total_items 32u 服务器启动以来存储过的内容总数 Total number of items stored by this server 
ever since it started bytes 64u 服务器当前存储内容所占用的字节数 Current number of bytes used by this server 
to store items curr_connections 32u 连接数量 Number of open connections total_connections 32u 服务器运行以来接受的连接总数 Total number of connections opened since 
the server started running connection_structures 32u 服务器分配的连接结构的数量 Number of connection structures allocated 
by the server cmd_get 32u 取回请求总数 Cumulative number of retrieval requests cmd_set 32u 存储请求总数 Cumulative number of storage requests get_hits 32u 请求成功的总次数 Number of keys that have been requested and 
found present get_misses 32u 请求失败的总次数 Number of items that have been requested 
and not found bytes_read 64u 服务器从网络读取到的总字节数 Total number of bytes read by this server 
from network bytes_written 64u 服务器向网络发送的总字节数 Total number of bytes sent by this server to 
network limit_maxbytes 32u 服务器在存储时被允许使用的字节总数 Number of bytes this server is allowed to
use for storage. 其它命令

“flush_all”命令有一个可选的数字参数。它总是执行成功,服务器会发送“OK\r\n”回应。它的效果是使已经存在的项目立即失效(缺省),或在指定的时间后。此后执行取回命令,将不会有任何内容返回(除非重新存储同样的键名)。flush_all 实际上没有立即释放项目所占用的内存,而是在随后陆续有新的项目被储存时执行。flush_all 效果具体如下:它导致所有更新时间早于flush_all所设定时间的项目,在被执行取回命令时命令被忽略。

在回应中,服务器发送:”VERSION \r\n” 是服务器的版本字串。接收此命令后,服务器关闭连接。不过,客户端可以在不再需要时,简单地关闭连接就行,并不一定需要发送这个命令。UDP 协议
当来自客户端的连接数远大于TCP连接的上限时,可以使用基于UDP的接口。UDP接口不能保证传输到位,所以只有在不要求成功的操作中使用;比如被用于一个“get”请求时,会因不当的缓存处理而发生错误或回应有遗失。每个UDP数据包都包含一个简单的帧头,数据之后的内容与TCP协议的描述类似。在执行所产生的数据流中,请求必须被包含在单独的一个UDP数据包中,但是回应可能跨越多个数据包。(只有“get”和“set”请求例外,跨越了多个数据包)帧头有8字节长,如下(均由16位整数组成,网络字节顺序,高位在前):

  • 0-1 请求ID
  • 2-3 序号
  • 4-5 该信息的数据包总数
  • 6-7 保留位,必须为0

请求ID有客户端提供。一般它会是一个从随机基数开始的递增值,不过客户端想用什么样的请求ID都可以。服务器的回应会包含一个和请求中的同样的ID。客户端使用请求ID来区分每一个回应。任何一个没有请求ID的数据包,可能是之前的请求遭到延迟而造成的,应该被丢弃。序号的返回是从0到n-1,n是该条信息的数据包数量。

memcache协议(二)

取回命令一行取回命令如下:get *\r\n- * 表示一个或多个键值,由空格隔开的字串.这行命令以后,客户端的等待0个或多个项目,每项都会收到一行文本,然后跟着数据区块。所有项目传送完毕后,服务器发送以下字串:
“END\r\n”来指示回应完毕。服务器用以下形式发送每项内容:VALUE \r\n
\r\n- 是所发送的键名- 是存储命令所设置的记号

是随后数据块的长度,*不包括* 它的界定符“\r\n”- 是发送的数据如果在取回请求中发送了一些键名,而服务器没有送回项目列表,这意味着服务器没这些键名(可能因为它们从未被存储,或者为给其他内容腾出空间而被删除,或者到期,或者被已客户端删除)。删除Deletion命令“delete”允许从外部删除内容:delete

是客户端要增加/减少的总数。回复为以下集中情形:

– “NOT_FOUND\r\n”指示该项内容的值,不存在。- \r\n ,是 增加/减少 。
注意”decr”命令发生下溢:如果客户端尝试减少的结果小于0时,结果会是0。”incr” 命令不会发生溢出。状态
命令”stats” 被用于查询服务器的运行状态和其他内部数据。有两种格式。不带参数的:
stats\r\n这会在随后输出各项状态、设定值和文档。另一种格式带有一些参数:
stats \r\n通过,服务器传回各种内部数据。因为随时可能发生变动,本文不提供参数的种类及其传回数据。各种状态受到无参数的”stats”命令后,服务器发送多行内容,如下:STAT \r\n服务器用以下一行来终止这个清单:END\r\n在每行状态中, 是状态的名字, 使状态的数据。 以下清单,是所有的状态名称,数据类型,和数据代表的含义。
在“类型”一列中,”32u”表示32位无符号整型,”64u”表示64位无符号整型,”32u:32u”表示用冒号隔开的两个32位无符号整型。 名称/Name 类型/Type 含义/Meaning pid 32u 服务器进程ID Process id of this server process uptime 32u 服务器运行时间,单位秒 Number of seconds this server has been running time 32u 服务器当前的UNIX时间 current UNIX time according to the server version string 服务器的版本号 Version string of this server rusage_user 32u:32u 该进程累计的用户时间
(秒:微妙) Accumulated user time for this process 
(seconds:microseconds) rusage_system 32u:32u 该进程累计的系统时间 
(秒:微妙) Accumulated system time for this process 
(seconds:microseconds) curr_items 32u 服务器当前存储的内容数量 Current number of items stored by the server total_items 32u 服务器启动以来存储过的内容总数 Total number of items stored by this server 
ever since it started bytes 64u 服务器当前存储内容所占用的字节数 Current number of bytes used by this server 
to store items curr_connections 32u 连接数量 Number of open connections total_connections 32u 服务器运行以来接受的连接总数 Total number of connections opened since 
the server started running connection_structures 32u 服务器分配的连接结构的数量 Number of connection structures allocated 
by the server cmd_get 32u 取回请求总数 Cumulative number of retrieval requests cmd_set 32u 存储请求总数 Cumulative number of storage requests get_hits 32u 请求成功的总次数 Number of keys that have been requested and 
found present get_misses 32u 请求失败的总次数 Number of items that have been requested 
and not found bytes_read 64u 服务器从网络读取到的总字节数 Total number of bytes read by this server 
from network bytes_written 64u 服务器向网络发送的总字节数 Total number of bytes sent by this server to 
network limit_maxbytes 32u 服务器在存储时被允许使用的字节总数 Number of bytes this server is allowed to
use for storage. 其它命令

“flush_all”命令有一个可选的数字参数。它总是执行成功,服务器会发送“OK\r\n”回应。它的效果是使已经存在的项目立即失效(缺省),或在指定的时间后。此后执行取回命令,将不会有任何内容返回(除非重新存储同样的键名)。flush_all 实际上没有立即释放项目所占用的内存,而是在随后陆续有新的项目被储存时执行。flush_all 效果具体如下:它导致所有更新时间早于flush_all所设定时间的项目,在被执行取回命令时命令被忽略。

在回应中,服务器发送:”VERSION \r\n” 是服务器的版本字串。接收此命令后,服务器关闭连接。不过,客户端可以在不再需要时,简单地关闭连接就行,并不一定需要发送这个命令。UDP 协议
当来自客户端的连接数远大于TCP连接的上限时,可以使用基于UDP的接口。UDP接口不能保证传输到位,所以只有在不要求成功的操作中使用;比如被用于一个“get”请求时,会因不当的缓存处理而发生错误或回应有遗失。每个UDP数据包都包含一个简单的帧头,数据之后的内容与TCP协议的描述类似。在执行所产生的数据流中,请求必须被包含在单独的一个UDP数据包中,但是回应可能跨越多个数据包。(只有“get”和“set”请求例外,跨越了多个数据包)帧头有8字节长,如下(均由16位整数组成,网络字节顺序,高位在前):

  • 0-1 请求ID
  • 2-3 序号
  • 4-5 该信息的数据包总数
  • 6-7 保留位,必须为0

请求ID有客户端提供。一般它会是一个从随机基数开始的递增值,不过客户端想用什么样的请求ID都可以。服务器的回应会包含一个和请求中的同样的ID。客户端使用请求ID来区分每一个回应。任何一个没有请求ID的数据包,可能是之前的请求遭到延迟而造成的,应该被丢弃。序号的返回是从0到n-1,n是该条信息的数据包数量。

数据库索引的使用(转)

为什么要创建索引呢?这是因为,创建索引可以大大提高系统的性能。第 一,通过创建唯一性索引,可以保证数据库表中每一行数据的唯一性。第二,可以大大加快数据的检索速度,这也是创建索引的最主要的原因。第三,可以加速表和 表之间的连接,特别是在实现数据的参考完整性方面特别有意义。第四,在使用分组和排序子句进行数据检索时,同样可以显著减少查询中分组和排序的时间。第 五,通过使用索引,可以在查询的过程中,使用优化隐藏器,提高系统的性能。 
也许会有人要问:增加索引有如此多的优点,为什么不 对表中的每一个列创建一个索引呢?这种想法固然有其合理性,然而也有其片面性。虽然,索引有许多优点,但是,为表中的每一个列都增加索引,是非常不明智 的。这是因为,增加索引也有许多不利的一个方面。第一,创建索引和维护索引要耗费时间,这种时间随着数据量的增加而增加。第二,索引需要占物理空间,除了 数据表占数据空间之外,每一个索引还要占一定的物理空间,如果要建立聚簇索引,那么需要的空间就会更大。第三,当对表中的数据进行增加、删除和修改的时 候,索引也要动态的维护,这样就降低了数据的维护速度。 
索引是建立在数据库表中的某些列的上面。因此,在创建索引的时候,应该 仔细考虑在哪些列上可以创建索引,在哪些列上不能创建索引。一般来说,应该在这些列上创建索引,例如:在经常需要搜索的列上,可以加快搜索的速度;在作为 主键的列上,强制该列的唯一性和组织表中数据的排列结构;在经常用在连接的列上,这些列主要是一些外键,可以加快连接的速度;在经常需要根据范围进行搜索 的列上创建索引,因为索引已经排序,其指定的范围是连续的;在经常需要排序的列上创建索引,因为索引已经排序,这样查询可以利用索引的排序,加快排序查询 时间;在经常使用在WHERE子句中的列上面创建索引,加快条件的判断速度。
同样,对于有些列不应该创建索引。一般来说,不应该创建索引的的 这些列具有下列特点:第一,对于那些在查询中很少使用或者参考的列不应该创建索引。这是因为,既然这些列很少使用到,因此有索引或者无索引,并不能提高查 询速度。相反,由于增加了索引,反而降低了系统的维护速度和增大了空间需求。第二,对于那些只有很少数据值的列也不应该增加索引。这是因为,由于这些列的 取值很少,例如人事表的性别列,在查询的结果中,结果集的数据行占了表中数据行的很大比例,即需要在表中搜索的数据行的比例很大。增加索引,并不能明显加 快检索速度。第三,对于那些定义为text, image和bit数据类型的列不应该增加索引。这是因为,这些列的数据量要么相当大,要么取值很少。第四,当修改性能远远大于检索性能时,不应该创建索 引。这是因为,修改性能和检索性能是互相矛盾的。当增加索引时,会提高检索性能,但是会降低修改性能。当减少索引时,会提高修改性能,降低检索性能。因 此,当修改性能远远大于检索性能时,不应该创建索引。
创建索引的方法和索引的特征

创建索引的方法 
创 建索引有多种方法,这些方法包括直接创建索引的方法和间接创建索引的方法。直接创建索引,例如使用CREATE INDEX语句或者使用创建索引向导,间接创建索引,例如在表中定义主键约束或者唯一性键约束时,同时也创建了索引。虽然,这两种方法都可以创建索引,但 是,它们创建索引的具体内容是有区别的。
使用CREATE INDEX语句或者使用创建索引向导来创建索引,这是最基本的索引创建方式,并且这种方法最具有柔性,可以定制创建出符合自己需要的索引。在使用这种方式 创建索引时,可以使用许多选项,例如指定数据页的充满度、进行排序、整理统计信息等,这样可以优化索引。使用这种方法,可以指定索引的类型、唯一性和复合 性,也就是说,既可以创建聚簇索引,也可以创建非聚簇索引,既可以在一个列上创建索引,也可以在两个或者两个以上的列上创建索引。 
通 过定义主键约束或者唯一性键约束,也可以间接创建索引。主键约束是一种保持数据完整性的逻辑,它限制表中的记录有相同的主键记录。在创建主键约束时,系统 自动创建了一个唯一性的聚簇索引。虽然,在逻辑上,主键约束是一种重要的结构,但是,在物理结构上,与主键约束相对应的结构是唯一性的聚簇索引。换句话 说,在物理实现上,不存在主键约束,而只存在唯一性的聚簇索引。同样,在创建唯一性键约束时,也同时创建了索引,这种索引则是唯一性的非聚簇索引。因此, 当使用约束创建索引时,索引的类型和特征基本上都已经确定了,由用户定制的余地比较小。 
当在表上定义主键或者唯一性键约束时, 如果表中已经有了使用CREATE INDEX语句创建的标准索引时,那么主键约束或者唯一性键约束创建的索引覆盖以前创建的标准索引。也就是说,主键约束或者唯一性键约束创建的索引的优先 级高于使用CREATE INDEX语句创建的索引。
索引的特征 

索引有两个特征,即唯一性索引和复合索引。 
唯 一性索引保证在索引列中的全部数据是唯一的,不会包含冗余数据。如果表中已经有一个主键约束或者唯一性键约束,那么当创建表或者修改表时,SQL Server自动创建一个唯一性索引。然而,如果必须保证唯一性,那么应该创建主键约束或者唯一性键约束,而不是创建一个唯一性索引。当创建唯一性索引 时,应该认真考虑这些规则:当在表中创建主键约束或者唯一性键约束时,SQL Server自动创建一个唯一性索引;如果表中已经包含有数据,那么当创建索引时,SQL Server检查表中已有数据的冗余性;每当使用插入语句插入数据或者使用修改语句修改数据时,SQL Server检查数据的冗余性:如果有冗余值,那么SQL Server取消该语句的执行,并且返回一个错误消息;确保表中的每一行数据都有一个唯一值,这样可以确保每一个实体都可以唯一确认;只能在可以保证实体 完整性的列上创建唯一性索引,例如,不能在人事表中的姓名列上创建唯一性索引,因为人们可以有相同的姓名。
复合索引就是一个索引创建在两个列 或者多个列上。在搜索时,当两个或者多个列作为一个关键值时,最好在这些列上创建复合索引。当创建复合索引时,应该考虑这些规则:最多可以把16个列合并 成一个单独的复合索引,构成复合索引的列的总长度不能超过900字节,也就是说复合列的长度不能太长;在复合索引中,所有的列必须来自同一个表中,不能跨 表建立复合列;在复合索引中,列的排列顺序是非常重要的,因此要认真排列列的顺序,原则上,应该首先定义最唯一的列,例如在(COL1,COL2)上的索 引与在(COL2,COL1)上的索引是不相同的,因为两个索引的列的顺序不同;为了使查询优化器使用复合索引,查询语句中的WHERE子句必须参考复合 索引中第一个列;当表中有多个关键列时,复合索引是非常有用的;使用复合索引可以提高查询性能,减少在一个表中所创建的索引数量。
索引的类型 
根据索引的顺序与数据表的物理顺序是否相同,可以把索引分成两种类型。一种是数据表的物理顺序与索引顺序相同的聚簇索引,另一种是数据表的物理顺序与索引顺序不相同的非聚簇索引。

聚簇索引的体系结构 
索 引的结构类似于树状结构,树的顶部称为叶级,树的其它部分称为非叶级,树的根部在非叶级中。同样,在聚簇索引中,聚簇索引的叶级和非叶级构成了一个树状结 构,索引的最低级是叶级。在聚簇索引中,表中的数据所在的数据页是叶级,在叶级之上的索引页是非叶级,索引数据所在的索引页是非叶级。在聚簇索引中,数据 值的顺序总是按照升序排列。 
应该在表中经常搜索的列或者按照顺序访问的列上创建聚簇索引。当创建聚簇索引时,应该考虑这些因 素:每一个表只能有一个聚簇索引,因为表中数据的物理顺序只能有一个;表中行的物理顺序和索引中行的物理顺序是相同的,在创建任何非聚簇索引之前创建聚簇 索引,这是因为聚簇索引改变了表中行的物理顺序,数据行按照一定的顺序排列,并且自动维护这个顺序;关键值的唯一性要么使用UNIQUE关键字明确维护, 要么由一个内部的唯一标识符明确维护,这些唯一性标识符是系统自己使用的,用户不能访问;聚簇索引的平均大小大约是数据表的百分之五,但是,实际的聚簇索 引的大小常常根据索引列的大小变化而变化;在索引的创建过程中,SQL Server临时使用当前数据库的磁盘空间,当创建聚簇索引时,需要1.2倍的表空间的大小,因此,一定要保证有足够的空间来创建聚簇索引。 
当 系统访问表中的数据时,首先确定在相应的列上是否存在有索引和该索引是否对要检索的数据有意义。如果索引存在并且该索引非常有意义,那么系统使用该索引访 问表中的记录。系统从索引开始浏览到数据,索引浏览则从树状索引的根部开始。从根部开始,搜索值与每一个关键值相比较,确定搜索值是否大于或者等于关键 值。这一步重复进行,直到碰上一个比搜索值大的关键值,或者该搜索值大于或者等于索引页上所有的关键值为止。

非聚簇索引的体系结构 
非聚簇索引的结构也是树状结构,与聚簇索引的结构非常类似,但是也有明显的不同。
在非聚簇索引中,叶级仅包含关键值,而没有包含数据行。非聚簇索引表示行的逻辑顺序。    非聚簇索引有两种体系结构:一种体系结构是在没有聚簇索引的表上创建非聚簇索引,另一种体系结构是在有聚簇索引的表上创建非聚簇索引。 
如 果一个数据表中没有聚簇索引,那么这个数据表也称为数据堆。当非聚簇索引在数据堆的顶部创建时,系统使用索引页中的行标识符指向数据页中的记录。行标识符 存储了数据所在位置的信息。数据堆是通过使用索引分配图(IAM)页来维护的。IAM页包含了数据堆所在簇的存储信息。在系统表sysindexes中, 有一个指针指向了与数据堆相关的第一个IAM页。系统使用IAM页在数据堆中浏览和寻找可以插入新的记录行的空间。这些数据页和在这些数据页中的记录没有 任何的顺序并且也没有链接在一起。在这些数据页之间的唯一的连接是IAM中记录的顺序。当在数据堆上创建了非聚簇索引时,叶级中包含了指向数据页的行标识 符。行标识符指定记录行的逻辑顺序,由文件ID、页号和行ID组成。这些行的标识符维持唯一性。非聚簇索引的叶级页的顺序不同于表中数据的物理顺序。这些 关键值在叶级中以升序维持。
当非聚簇索引创建在有聚簇索引的表上的时候,系统使用索引页中的指向聚簇索引的聚簇键。聚簇键存储了数据的位置信 息。如果某一个表有聚簇索引,那么非聚簇索引的叶级包含了映射到聚簇键的聚簇键值,而不是映射到物理的行标识符。当系统访问有非聚簇索引的表中数据时,并 且这种非聚簇索引创建在聚簇索引上,那么它首先从非聚簇索引来找到指向聚簇索引的指针,然后通过使用聚簇索引来找到数据。 
当需要以多种方式检索数据时,非聚簇索引是非常有用的。当创建非聚簇索引时,要考虑这些情况:在缺省情况下,所创建的索引是非聚簇索引;在每一个表上面,可以创建不多于249个非聚簇索引,而聚簇索引最多只能有一个。
系统如何访问表中的数据
一 般地,系统访问数据库中的数据,可以使用两种方法:表扫描和索引查找。第一种方法是表扫描,就是指系统将指针放置在该表的表头数据所在的数据页上,然后按 照数据页的排列顺序,一页一页地从前向后扫描该表数据所占有的全部数据页,直至扫描完表中的全部记录。在扫描时,如果找到符合查询条件的记录,那么就将这 条记录挑选出来。最后,将全部挑选出来符合查询语句条件的记录显示出来。第二种方法是使用索引查找。索引是一种树状结构,其中存储了关键字和指向包含关键 字所在记录的数据页的指针。当使用索引查找时,系统沿着索引的树状结构,根据索引中关键字和指针,找到符合查询条件的的记录。最后,将全部查找到的符合查 询语句条件的记录显示出来。
在SQL Server中,当访问数据库中的数据时,由SQL Server确定该表中是否有索引存在。如果没有索引,那么SQL Server使用表扫描的方法访问数据库中的数据。查询处理器根据分布的统计信息生成该查询语句的优化执行规划,以提高访问数据的效率为目标,确定是使用 表扫描还是使用索引。
索引的选项 
在创建索引时,可以指定一些选项,通过使用这些选项,可以优化索引的性能。这些选项包括FILLFACTOR选项、PAD_INDEX选项和SORTED_DATA_REORG选项。
使 用FILLFACTOR选项,可以优化插入语句和修改语句的性能。当某个索引页变满时,SQL Server必须花费时间分解该页,以便为新的记录行腾出空间。使用FILLFACTOR选项,就是在叶级索引页上分配一定百分比的自由空间,以便减少页 的分解时间。当在有数据的表中创建索引时,可以使用FILLFACTOR选项指定每一个叶级索引节点的填充的百分比。缺省值是0,该数值等价于100。在 创建索引的时候,内部索引节点总是留有了一定的空间,这个空间足够容纳一个或者两个表中的记录。在没有数据的表中,当创建索引的时候,不要使用该选项,因 为这时该选项是没有实际意义的。另外,该选项的数值在创建时指定以后,不能动态地得到维护,因此,只应该在有数据的表中创建索引时才使用。 
PAD_INDEX 选项将FILLFACTOR选项的数值同样也用于内部的索引节点,使内部的索引节点的填充度与叶级索引的节点中的填充度相同。如果没有指定 FILLFACTOR选项,那么单独指定PAD_INDEX选项是没有实际意义的,这是因为PAD_INDEX选项的取值是由FILLFACTOR选项的 取值确定的。
当创建聚簇索引时,SORTED_DATA_REORG选项清除排序,因此可以减少建立聚簇索引所需要的时间。当在一个已经变成 碎块的表上创建或者重建聚簇索引时,使用SORTED_DATA_REORG选项可以压缩数据页。当重新需要在索引上应用填充度时,也使用该选项。当使用 SORTED_DATA_REORG选项时,应该考虑这些因素:SQL Server确认每一个关键值是否比前一个关键值高,如果都不高,那么不能创建索引;SQL Server要求1.2倍的表空间来物理地重新组织数据;使用SORTED_DATA_REORG选项,通过清除排序进程而加快索引创建进程;从表中物理 地拷贝数据;当某一个行被删除时,其所占的空间可以重新利用;创建全部非聚簇索引;如果希望把叶级页填充到一定的百分比,可以同时使用 FILLFACTOR选项和SORTED_DATA_REORG选项。
索引的维护 
为了维护系统性能,索引在创建之后,由于频繁地对数据进行增加、删除、修改等操作使得索引页发生碎块,因此,必须对索引进行维护。 
使 用DBCC SHOWCONTIG语句,可以显示表的数据和索引的碎块信息。当执行DBCC SHOWCONTIG语句时,SQL Server浏览叶级上的整个索引页,来确定表或者指定的索引是否严重碎块。DBCC SHOWCONTIG语句还能确定数据页和索引页是否已经满了。当对表进行大量的修改或者增加大量的数据之后,或者表的查询非常慢时,应该在这些表上执行 DBCC SHOWCONTIG语句。当执行DBCC SHOWCONTIG语句时,应该考虑这些因素:当执行DBCC SHOWCONTIG语句时,SQL Server要求指定表的ID号或者索引的ID号,表的ID号或者索引的ID号可以从系统表sysindexes中得到;应该确定多长时间使用一次 DBCC SHOWCONTIG语句,这个时间长度要根据表的活动情况来定,每天、每周或者每月都可以。
使用DBCC DBREINDEX语句重建表的一个或者多个索引。当希望重建索引和当表上有主键约束或者唯一性键约束时,执行DBCC DBREINDEX语句。除此之外,执行DBCC DBREINDEX语句还可以重新组织叶级索引页的存储空间、删除碎块和重新计算索引统计。当使用执行DBCC DBREINDEX语句时,应该考虑这些因素:根据指定的填充度,系统重新填充每一个叶级页;使用DBCC DBREINDEX语句重建主键约束或者唯一性键约束的索引;使用SORTED_DATA_REORG选项可以更快地创建聚簇索引,如果没有排列关键值,那么不能使用DBCC DBREINDEX语句;DBCC DBREINDEX语句不支持系统表。另外,还可以使用数据库维护规划向导自动地进行重建索引的进程。 
统 计信息是存储在SQL Server中的列数据的样本。这些数据一般地用于索引列,但是还可以为非索引列创建统计。SQL Server维护某一个索引关键值的分布统计信息,并且使用这些统计信息来确定在查询进程中哪一个索引是有用的。查询的优化依赖于这些统计信息的分布准确 度。查询优化器使用这些数据样本来决定是使用表扫描还是使用索引。当表中数据发生变化时,SQL Server周期性地自动修改统计信息。索引统计被自动地修改,索引中的关键值显著变化。统计信息修改的频率由索引中的数据量和数据改变量确定。例如,如 果表中有10000行数据,1000行数据修改了,那么统计信息可能需要修改。然而,如果只有50行记录修改了,那么仍然保持当前的统计信息。除了系统自 动修改之外,用户还可以通过执行UPDATE STATISTICS语句或者sp_updatestats系统存储过程来手工修改统计信息。使用UPDATE STATISTICS语句既可以修改表中的全部索引,也可以修改指定的索引。
使用SHOWPLAN和STATISTICS IO语句可以分析索引和查询性能。使用这些语句可以更好地调整查询和索引。SHOWPLAN语句显示在连接表中使用的查询优化器的每一步以及表明使用哪一 个索引访问数据。使用SHOWPLAN语句可以查看指定查询的查询规划。当使用SHOWPLAN语句时,应该考虑这些因素。SET SHOWPLAN_ALL语句返回的输出结果比SET SHOWPLAN_TEXT语句返回的输出结果详细。然而,应用程序必须能够处理SET SHOWPLAN_ALL语句返回的输出结果。SHOWPLAN语句生成的信息只能针对一个会话。如果重新连接SQL Server,那么必须重新执行SHOWPLAN语句。STATISTICS IO语句表明输入输出的数量,这些输入输出用来返回结果集和显示指定查询的逻辑的和物理的I/O的信息。可以使用这些信息来确定是否应该重写查询语句或者 重新设计索引。使用STATISTICS IO语句可以查看用来处理指定查询的I/O信息。
就象SHOWPLAN语句一样,优化器隐藏也用来 调整查询性能。优化器隐藏可以对查询性能提供较小的改进,并且如果索引策略发生了改变,那么这种优化器隐藏就毫无用处了。因此,限制使用优化器隐藏,这是 因为优化器隐藏更有效率和更有柔性。当使用优化器隐藏时,考虑这些规则:指定索引名称、当index_id为0时为使用表扫描、当index_id为1时 为使用聚簇索引;优化器隐藏覆盖查询优化器,如果数据或者环境发生了变化,那么必须修改优化器隐藏。
索引调整向导
索引调整向导是一种工具,可以分析一系列数据库的查询语句,提供使用一系列数据库索引的建议,优化整个查询语句的性能。对于查询语句,需要指定下列内容:
查询语句,这是将要优化的工作量 
包含了这些表的数据库,在这些表中,可以创建索引,提高查询性能 
在分析中使用的表 
在分析中,考虑的约束条件,例如索引可以使用的最大磁盘空间  
这 里指的工作量,可以来自两个方面:使用SQL Server捕捉的轨迹和包含了SQL语句的文件。索引调整向导总是基于一个已经定义好的工作量。如果一个工作量不能反映正常的操作,那么它建议使用的索 引不是实际的工作量上性能最好的索引。索引调整向导调用查询分析器,使用所有可能的组合评定在这个工作量中每一个查询语句的性能。然后,建议在整个工作量 上可以提高整个查询语句的性能的索引。如果没有供索引调整向导来分析的工作量,那么可以使用图解器立即创建它。一旦决定跟踪一条正常数据库活动的描述样 本,向导能够分析这种工作量和推荐能够提高数据库工作性能的索引配置。
索引调整向导对工作量进行分析之后,可以查看到一系列的报告,还可以使该向导立即创建所建议的最佳索引,或者使这项工作成为一种可以调度的作业,或者生成一个包含创建这些索引的SQL语句的文件。
索引调整向导允许为SQL Server数据库选择和创建一种理想的索引组合和统计,而不要求对数据库结构、工作量或者SQL Server内部达到专家的理解程度。总之,索引调整向导能够作到以下几个方面的工作:
通过使用查询优化器来分析工作量中的查询任务,向有大量工作量的数据库推荐一种最佳的索引混合方式 
分析按照建议作出改变之后的效果,包括索引的用法、表间查询的分布和大量工作中查询的工作效果 
为少量查询任务推荐调整数据库的方法  
通过设定高级选项如磁盘空间约束、最大的查询语句数量和每个索引的最多列的数量等,允许定制推荐方式 
图解器 
图 解器能够实时抓取在服务器中运行的连续图片,可以选取希望监测的项目和事件,包括Transact-SQL语句和批命令、对象的用法、锁定、安全事件和错 误。图解器能够过滤这些事件,仅仅显示用户关心的问题。可以使用同一台服务器或者其他服务器重复已经记录的跟踪事件,重新执行那些已经作了记录的命令。通 过集中处理这些事件,就能够很容易监测和调试SQL Server中出现的问题。通过对特定事件的研究,监测和调试SQL Server问题变得简单多了。
查询处理器 
查询处理器是一种可以完成许多工作的多用途的工具。在查询处理器中,可 以交互式地输入和执行各种Transact-SQL语句,并且在一个窗口中可以同时查看Transact-SQL语句和其结果集;可以在查询处理器中同时 执行多个Transact-SQL语句,也可以执行脚本文件中的部分语句;提供了一种图形化分析查询语句执行规划的方法,可以报告由查询处理器选择的数据 检索方法,并且可以根据查询规划调整查询语句的执行,提出执行可以提高性能的优化索引建议,这种建议只是针对一条查询语句的索引建议,只能提高这一条查询 语句的查询性能。
系统为每一个索引创建一个分布页,统计信息就是指存储在分布页上的某一个表中的一个或者多个索引的关键值的分布信息。当执行 查询语句时,为了提高查询速度和性能,系统可以使用这些分布信息来确定使用表的哪一个索引。查询处理器就是依赖于这些分布的统计信息,来生成查询语句的执 行规划。执行规划的优化程度依赖于这些分布统计信息的准确步骤的高低程度。如果这些分布的统计信息与索引的物理信息非常一致,那么查询处理器可以生成优化 程度很高的执行规划。相反,如果这些统计信息与索引的实际存储的信息相差比较大,那么查询处理器生成的执行规划的优化程度则比较低。 
查 询处理器从统计信息中提取索引关键字的分布信息,除了用户可以手工执行UPDATE STATISTICS之外,查询处理器还可以自动收集统计这些分布信息。这样,就能够充分保证查询处理器使用最新的统计信息,保证执行规划具有很高的优化 程度,减少了维护的需要。当然,使用查询处理器生成的执行规划,也有一些限制。例如,使用执行规划只能提高单个查询语句的性能,但是可能对整个系统的性能 产生正面的或者付面的影响,因此,要想提高整个系统的查询性能,应该使用索引调整向导这样的工具。
结论 
在以前的 SQL Server版本中,在一个查询语句中,一个表上最多使用一个索引。而在SQL Server 7.0中,索引操作得到了增强。SQL Server现在使用索引插入和索引联合算法来实现在一个查询语句中的可以使用多个索引。共享的行标识符用于连接同一个表上的两个索引。如果某个表中有一 个聚簇索引,因此有一个聚簇键,那么该表上的全部非聚簇索引的叶节点使用该聚簇键作为行定位器,而不是使用物理记录标识符。如果表中没有聚簇索引,那么非 聚簇索引继续使用物理记录标识符指向数据页。在上面的两种情况中,行定位器是非常稳定的。当聚簇索引的叶节点分开时,由于行定位器是有效的,所以非聚簇索 引不需要被修改。如果表中没有聚簇索引,那么页的分开就不会发生。而在以前的版本中,非聚簇索引使用物理记录标识符如页号和行号,作为行的定位器。例如, 如果聚簇索引(数据页)发生分解时,许多记录行被移动到了一个新的数据页,因此有了多个新的物理记录标识符。那么,所有的非聚簇索引都必须使用这些新的物 理记录标识符进行修改,这样就需要耗费大量的时间和资源。 
索引调整向导无论对熟练用户还是新用户,都是一个很好的工具。熟练用户可以使用该向导创建一个基本的索引配置,然后在基本的索引配置上面进行调整和定制。新用户可以使用该向导快速地创建优化的索引。

mysql explain的使用说明

转载自

http://www.51testing.com/?uid-110296-action-viewspace-itemid-69549

explain显示了mysql如何使用索引来处理select语句以及连接表。可以帮助选择更好的索引和写出更优化的查询语句。

使用方法,在select语句前加上explain就可以了:

如:explain select surname,first_name form a,b where a.id=b.id

分析结果形式如下:

table

type

possible_keys

key

key_len

ref

rows

Extra

a

range

id

first_name

First_name

9

NULL

23112

Using where

Using temporary

Using filesort

 b

ref

id

first_name

id

4

id

2

Using where

 

EXPLAIN列的解释:

table

显示这一行的数据是关于哪张表的

type

 

这是重要的列,显示连接使用了何种类型。从最好到最差的连接类型为const、eq_reg、ref、range、indexhe和ALL

possible_keys

显示可能应用在这张表中的索引。如果为空,没有可能的索引。可以为相关的域从WHERE语句中选择一个合适的语句

key

 

实际使用的索引。如果为NULL,则没有使用索引。很少的情况下,MYSQL会选择优化不足的索引。这种情况下,可以在SELECT语句中使用USE INDEX(indexname)来强制使用一个索引或者用IGNORE INDEX(indexname)来强制MYSQL忽略索引

key_len

 

使用的索引的长度。在不损失精确性的情况下,长度越短越好

ref

 

显示索引的哪一列被使用了,如果可能的话,是一个常数

rows

 

MYSQL认为必须检查的用来返回请求数据的行数

Extra

 

 

关于MYSQL如何解析查询的额外信息。将在表4.3中讨论,但这里可以看到的坏的例子是Using temporary和Using filesort,意思MYSQL根本不能使用索引,结果是检索会很慢

 

extra列返回的描述的意义

Distinct

一旦MYSQL找到了与行相联合匹配的行,就不再搜索了

Not exists

 

MYSQL优化了LEFT JOIN,一旦它找到了匹配LEFT JOIN标准的行,

就不再搜索了

Range checked for each

Record(index map:#)

 

没有找到理想的索引,因此对于从前面表中来的每一个

行组合,MYSQL检查使用哪个索引,并用它来从表中返回行。

这是使用索引的最慢的连接之一

Using filesort

 

看到这个的时候,查询就需要优化了。MYSQL需要进行额外的步骤

来发现如何对返回的行排序。它根据连接类型以及存储排序键值和

匹配条件的全部行的行指针来排序全部行

Using index

 

列数据是从仅仅使用了索引中的信息而没有读取实际的行动的表返回的,

这发生在对表的全部的请求列都是同一个索引的部分的时候

Using temporary

 

看到这个的时候,查询需要优化了。

这里,MYSQL需要创建一个临时表来存储结果,

这通常发生在对不同的列集进行ORDER BY上,而不是GROUP BY上

Where used

 

使用了WHERE从句来限制哪些行将与下一张表匹配或者是返回给用户。

如果不想返回表中的全部行,并且连接类型ALL或index,这就会发生,

或者是查询有问题

 

不同连接类型的解释(按照效率高低的顺序排序)

system

表只有一行:system表。这是const连接类型的特殊情况

const

 

表中的一个记录的最大值能够匹配这个查询(索引可以是主键或惟一索引)。因为只有一行,这个值实际就是常数,因为MYSQL先读这个值然后把它当做常数来对待

eq_ref

 

在连接中,MYSQL在查询时,从前面的表中,对每一个记录的联合都从表中读取一个记录,它在查询使用了索引为主键或惟一键的全部时使用

ref

 

这个连接类型只有在查询使用了不是惟一或主键的键或者是这些类型的部分(比如,利用最左边前缀)时发生。对于之前的表的每一个行联合,全部记录都将从表中读出。这个类型严重依赖于根据索引匹配的记录多少—越少越好

range

 

这个连接类型使用索引返回一个范围中的行,比如使用>或<查找东西时发生的情况

index

 

这个连接类型对前面的表中的每一个记录联合进行完全扫描(比ALL更好,因为索引一般小于表数据)

ALL

 

这个连接类型对于前面的每一个记录联合进行完全扫描,这一般比较糟糕,应该尽量避免

telnet 查看memcache变量

memcached的服务器客户端通信并不使用复杂的XML等格式,而使用简单的基于文本行的协议。因此,通过telnet 也能在memcached上保存数据、取得数据。下面是例子。

$ telnet localhost 11211Trying 127.0.0.1…Connected to localhost.localdomain (127.0.0.1).Escape character is ‘^]’.set foo 0 0 3 (保存命令)bar (数据)STORED (结果)get foo (取得命令)VALUE foo 0 3 (数据)bar (数据)delete fooDELETED