mysql中。KEY `userid` (`userid`),
KEY `logintime` (`logintime`),与
KEY `userid` (`userid`,`logintime`)
有什么区别?查询效率上哪个更好些。

解决方案 »

  1.   

    前为单一索引,后者为复合索引,
    如果你的SQL语句中有用到`userid`,`logintime`字段时,后者效率高一些,根据具体情况来判定
      

  2.   


    如果单查userid 或 logintime 是不是前者效率更好些?
      

  3.   

    有个小问题。mysql中怎么是KEY `userid` (`userid`), 而不是index userid(userid)?
      

  4.   

    KEY和INDEX是一码事。KEY `userid` (`userid`),
    KEY `logintime` (`logintime`),与
    KEY `userid` (`userid`,`logintime`)单独查询某一个字段的时候,分开的索引效率好,它是索引大小都要小很多,查询起来肯定快一些。
    多个字段的索引,如果查询的条件都被索引到了,那就成了覆盖索引了,所有数据都可以通过索引得到,效率刚刚地。完全避免了读取数据行了。但是索引本身就大了,因为它要包含2个字段了。
      

  5.   


    一个是两个单独的索引,另外一个KEY `userid` (`userid`,`logintime`)是复合索引。效率要看你的具体查询,没有哪个好哪个坏。如果是 where userid='1234' 则 KEY `userid` (`userid`), 或者 KEY `userid` (`userid`,`logintime`)都并不多。
    如果是 where `logintime` ='2001-10-01' 则 KEY `logintime` (`logintime`),有用,其它的索引无意义。
    如果是 where  userid='1234' and `logintime` ='2001-10-01' 则 KEY `userid` (`userid`,`logintime`)效率会比较高。
      

  6.   

    关于优化,其实本身并不复杂,关键是你要掌握基础知道。否则就会感到无从下手。建议先看一下 《数据库系统概论(第四版)》 王珊 萨师煊   高等教育出版社 (掌握基础知识和概念) 
    中的SQL优化章节。然后再看
    MySQL官方文档 http://dev.mysql.com/doc/refman/5.1/zh/index.html中的优化部分。
      

  7.   


    MYSQL的执行计划会自动去统计表的各种信息,如记录数,索引等,然后一个个的去算“开销”,哪种开销小,就用哪个执行计划。所以有时候执行计划和我们设计的并不一样。INNODB是根据主键聚集的,每个普通索引都会包含有主键的信息,所以主键设计的时候一定要小。MYSQL使用的是最左前缀索引,所以建立复合索引的时候,哪个字段放到最左边是有技巧的,查询最多的那个字段应该放在索引的最左边。
      

  8.   

    借这个帖子更进一步探讨一下索引技术。如果表上只有KEY `userid` (`userid`,`logintime`)这一个索引,那么
    select * from tbname where logintime='2010-01-01 00:23:22';
    这个查询是使用不到索引的。原因是这个字段并不在组合索引的最左边。
    select * from tbname where userid=100;  这样就会用到这个索引。抛砖引玉,版主大哥们出来分享一下你们的经验啊。
      

  9.   

    18楼的这个例子举得并不恰当。因为USERID已经是默认主键索引了。应该用另外2个字段来做组合索引,效果更加直观。
      

  10.   

    上面都讨论查询上的效率。不知道 
    KEY `userid` (`userid`,`logintime`)
    与两个索引
    KEY `userid` (`userid`),KEY `logintime` (`logintime`)在插入,更新,删除操作上的效率如何。大家继续~
      

  11.   


    没什么可分享的,这些都已经在文档中有详细说明了。读完下面文章花不了5分钟。与其我花10分写个100字的并不准确的摘要,还不如想学的人自己看一下文档。
    [Quote=MySQL 5.1参考手册]
    7.4.5. MySQL如何使用索引
    索引用于快速找出在某个列中有一特定值的行。不使用索引,MySQL必须从第1条记录开始然后读完整个表直到找出相关的行。表越大,花费的时间越多。如果表中查询的列有一个索引,MySQL能快速到达一个位置去搜寻到数据文件的中间,没有必要看所有数据。如果一个表有1000行,这比顺序读取至少快100倍。注意如果你需要访问大部分行,顺序读取要快得多,因为此时我们避免磁盘搜索。大多数MySQL索引(PRIMARY KEY、UNIQUE、INDEX和FULLTEXT)在B树中存储。只是空间列类型的索引使用R-树,并且MEMORY表还支持hash索引。字符串自动地压缩前缀和结尾空格。参见13.1.4节,“CREATE INDEX语法”。总的来说,按后面的讨论使用索引。本节最后描述hash索引(用于MEMORY表)的特征。索引用于下面的操作:·         快速找出匹配一个WHERE子句的行。·         删除行。如果可以在多个索引中进行选择,MySQL通常使用找到最少行的索引。·         当执行联接时,从其它表检索行。·         对具体有索引的列key_col找出MAX()或MIN()值。由预处理器进行优化,检查是否对索引中在key_col之前发生所有关键字元素使用了WHERE key_part_# = constant。在这种情况下,MySQL为每个MIN()或MAX()表达式执行一次关键字查找,并用常数替换它。如果所有表达式替换为常量,查询立即返回。例如:·                SELECT MIN(key_part2),MAX(key_part2)
    ·                    FROM tbl_name WHERE key_part1=10;
    ·         如果对一个可用关键字的最左面的前缀进行了排序或分组(例如,ORDER BY key_part_1,key_part_2),排序或分组一个表。如果所有关键字元素后面有DESC,关键字以倒序被读取。参见7.2.12节,“MySQL如何优化ORDER BY”。·         在一些情况中,可以对一个查询进行优化以便不用查询数据行即可以检索值。如果查询只使用来自某个表的数字型并且构成某些关键字的最左面前缀的列,为了更快,可以从索引树检索出值。·                SELECT key_part3 FROM tbl_name
    ·                    WHERE key_part1=1
    假定你执行下面的SELECT语句:mysql> SELECT * FROM tbl_name WHERE col1=val1 AND col2=val2;
    如果col1和col2上存在一个多列索引,可以直接取出相应行。如果col1和col2上存在单列索引,优化器试图通过决定哪个索引将找到更少的行来找出更具限制性的索引并且使用该索引取行。如果表有一个多列索引,优化器可以使用最左面的索引前缀来找出行。例如,如果有一个3列索引(col1,col2,col3),则已经对(col1)、(col1,col2)和(col1,col2,col3)上的搜索进行了索引。如果列不构成索引最左面的前缀,MySQL不能使用局部索引。假定有下面显示的SELECT语句。 
    SELECT * FROM tbl_name WHERE col1=val1;
    SELECT * FROM tbl_name WHERE col1=val1 AND col2=val2;
     
    SELECT * FROM tbl_name WHERE col2=val2;
    SELECT * FROM tbl_name WHERE col2=val2 AND col3=val3;
     
    如果 (col1,col2,col3)有一个索引,只有前2个查询使用索引。第3个和第4个查询确实包括索引的列,但(col2)和(col2,col3)不是 (col1,col2,col3)的最左边的前缀。也可以在表达式通过=、>、>=、<、<=或者BETWEEN操作符使用B-树索引进行列比较。如果LIKE的参数是一个不以通配符开头的常量字符串,索引也可以用于LIKE比较。例如,下面的SELECT语句使用索引:SELECT * FROM tbl_name WHERE key_col LIKE 'Patrick%';
    SELECT * FROM tbl_name WHERE key_col LIKE 'Pat%_ck%';
    在第1个语句中,只考虑带'Patrick' <=key_col < 'Patricl'的行。在第2个语句中,只考虑带'Pat' <=key_col < 'Pau'的行。下面的SELECT语句不使用索引:SELECT * FROM tbl_name WHERE key_col LIKE '%Patrick%';
    SELECT * FROM tbl_name WHERE key_col LIKE other_col;
    在第一条语句中,LIKE值以一个通配符字符开始。在第二条语句中,LIKE值不是一个常数。如果使用... LIKE '%string%'并且string超过3个字符,MySQL使用Turbo Boyer-Moore算法初始化字符串的模式然后使用该模式来更快地进行搜索。如果col_name被索引,使用col_name IS NULL的搜索将使用索引。任何不跨越WHERE子句中的所有AND级的索引不用于优化查询。换句话说,为了能够使用索引,必须在每个AND组中使用索引前缀。下面的WHERE子句使用索引:... WHERE index_part1=1 AND index_part2=2 AND other_column=3
        /* index = 1 OR index = 2 */
    ... WHERE index=1 OR A=10 AND index=2
        /* optimized like "index_part1='hello'" */
    ... WHERE index_part1='hello' AND index_part3=5
        /* Can use index on index1 but not on index2 or index3 */
    ... WHERE index1=1 AND index2=2 OR index1=3 AND index3=3;
    下面的WHERE子句不使用索引:    /* index_part1 is not used */
    ... WHERE index_part2=1 AND index_part3=2
     
        /*  Index is not used in both parts of the WHERE clause  */
    ... WHERE index=1 OR A=10
     
        /* No index spans all rows  */
    ... WHERE index_part1=1 OR index_part2=10
    有时MySQL不使用索引,即使有可用的索引。一种情形是当优化器估计到使用索引将需要MySQL访问表中的大部分行时。(在这种情况下,表扫描可能会更快些,因为需要的搜索要少)。然而,如果此类查询使用LIMIT只搜索部分行,MySQL则使用索引,因为它可以更快地找到几行并在结果中返回。Hash索引还有一些其它特征:·         它们只用于使用=或<=>操作符的等式比较(但很快)。它们用于比较 操作符,例如发现范围值的<。·         优化器不能使用hash索引来加速ORDER BY操作。(该类索引不能用来按顺序搜索下一个条目)。·         MySQL不能确定在两个值之间大约有多少行(这被范围优化器用来确定使用哪个索引)。如果你将一个MyISAM表改为hash-索引的MEMORY表,会影响一些查询。·         只能使用整个关键字来搜索一行。(用B-树索引,任何关键字的最左面的前缀可用来找到行)。[/Quote]
      

  12.   


    楼主如果想学的话,则建议抽空看一下那本基础教材。很显然,在插入,更新,删除操作时,除了正常的记录数据需要插入外,MYSQL还要会花额外的开销去维护索引。
      

  13.   

    狼头哥推荐的那本书,我看到第二遍,才有所理解。里面一些以标准SQL举的例子,在MYSQL里面并不符合。坚持读完10遍,应该能够有所收获。
      

  14.   


    已看了官方文档了,呵呵  http://dev.mysql.com/doc/refman/5.1/zh/index.html
      

  15.   

    前者建了两个索引,但在查询的时候系统会跟据情况选择一个索引,所以如果同时涉及两个字段的查询的话后者快一点,只涉及userid的话是一样快,如果只涉及logintime的话是前者快,后者没有logintime索引