精华内容
下载资源
问答
  • 数据库索引使用数据结构

    千次阅读 2017-09-01 00:07:45
    数据库索引,是数据库管理系统中一个排序数据结构,以协助快速查询、更新数据库表中数据索引的实现通常使用B树及其变种B+树。 在数据之外,数据库系统还维护着满足特定查找算法的数据结构,这些数据结构以某种...

    强烈建议参阅链接:http://www.linezing.com/blog/?p=798#nav-1


    说白了,索引问题就是一个查找问题。。。


    数据库索引,是数据库管理系统中一个排序的数据结构,以协助快速查询、更新数据库表中数据。索引的实现通常使用B树及其变种B+树

    在数据之外,数据库系统还维护着满足特定查找算法的数据结构,这些数据结构以某种方式引用(指向)数据,这样就可以在这些数据结构上实现高级查找算法。这种数据结构,就是索引。

    为表设置索引要付出代价的:一是增加了数据库的存储空间,二是在插入和修改数据时要花费较多的时间(因为索引也要随之变动)。


    上图展示了一种可能的索引方式。左边是数据表,一共有两列七条记录,最左边的是数据记录的物理地址(注意逻辑上相邻的记录在磁盘上也并不是一定物理相邻的)。为了加快Col2的查找,可以维护一个右边所示的二叉查找树,每个节点分别包含索引键值和一个指向对应数据记录物理地址的指针,这样就可以运用二叉查找在O(log2n)的复杂度内获取到相应数据。


    创建索引可以大大提高系统的性能。

    第一,通过创建唯一性索引,可以保证数据库表中每一行数据的唯一性。

    第二,可以大大加快数据的检索速度,这也是创建索引的最主要的原因。

    第三,可以加速表和表之间的连接,特别是在实现数据的参考完整性方面特别有意义。

    第四,在使用分组和排序子句进行数据检索时,同样可以显著减少查询中分组和排序的时间。

    第五,通过使用索引,可以在查询的过程中,使用优化隐藏器,提高系统的性能。 


    也许会有人要问:增加索引有如此多的优点,为什么不对表中的每一个列创建一个索引呢?因为,增加索引也有许多不利的方面。

    第一,创建索引和维护索引要耗费时间,这种时间随着数据量的增加而增加。

    第二,索引需要占物理空间,除了数据表占数据空间之外,每一个索引还要占一定的物理空间,如果要建立聚簇索引,那么需要的空间就会更大。

    第三,当对表中的数据进行增加、删除和修改的时候,索引也要动态的维护,这样就降低了数据的维护速度。


    索引是建立在数据库表中的某些列的上面。在创建索引的时候,应该考虑在哪些列上可以创建索引,在哪些列上不能创建索引。一般来说,应该在这些列上创建索引:在经常需要搜索的列上,可以加快搜索的速度;在作为主键的列上,强制该列的唯一性和组织表中数据的排列结构;在经常用在连接的列上,这些列主要是一些外键,可以加快连接的速度;在经常需要根据范围进行搜索的列上创建索引,因为索引已经排序,其指定的范围是连续的;在经常需要排序的列上创建索引,因为索引已经排序,这样查询可以利用索引的排序,加快排序查询时间;在经常使用在WHERE子句中的列上面创建索引,加快条件的判断速度。


    同样,对于有些列不应该创建索引。一般来说,不应该创建索引的的这些列具有下列特点:

    第一,对于那些在查询中很少使用或者参考的列不应该创建索引。这是因为,既然这些列很少使用到,因此有索引或者无索引,并不能提高查询速度。相反,由于增加了索引,反而降低了系统的维护速度和增大了空间需求。

    第二,对于那些只有很少数据值的列也不应该增加索引。这是因为,由于这些列的取值很少,例如人事表的性别列,在查询的结果中,结果集的数据行占了表中数据行的很大比例,即需要在表中搜索的数据行的比例很大。增加索引,并不能明显加快检索速度。

    第三,对于那些定义为text, image和bit数据类型的列不应该增加索引。这是因为,这些列的数据量要么相当大,要么取值很少。

    第四,当修改性能远远大于检索性能时,不应该创建索引。这是因为,修改性能和检索性能是互相矛盾的。当增加索引时,会提高检索性能,但是会降低修改性能。当减少索引时,会提高修改性能,降低检索性能。因此,当修改性能远远大于检索性能时,不应该创建索引。


    根据数据库的功能,可以在数据库设计器中创建三种索引:唯一索引、主键索引和聚集索引

    唯一索引 

    唯一索引是不允许其中任何两行具有相同索引值的索引。

    当现有数据中存在重复的键值时,大多数数据库不允许将新创建的唯一索引与表一起保存。数据库还可能防止添加将在表中创建重复键值的新数据。例如,如果在employee表中职员的姓(lname)上创建了唯一索引,则任何两个员工都不能同姓。
    主键索引
    数据库表经常有一列或列组合,其值唯一标识表中的每一行。该列称为表的主键。
    在数据库关系图中为表定义主键将自动创建主键索引,主键索引是唯一索引的特定类型。该索引要求主键中的每个值都唯一。当在查询中使用主键索引时,它还允许对数据的快速访问。
    聚集索引
    在聚集索引中,表中行的物理顺序与键值的逻辑(索引)顺序相同。一个表只能包含一个聚集索引。

    如果某索引不是聚集索引,则表中行的物理顺序与键值的逻辑顺序不匹配。与非聚集索引相比,聚集索引通常提供更快的数据访问速度。



    局部性原理与磁盘预读

    由于存储介质的特性,磁盘本身存取就比主存慢很多,再加上机械运动耗费,磁盘的存取速度往往是主存的几百分分之一,因此为了提高效率,要尽量减少磁盘I/O。为了达到这个目的,磁盘往往不是严格按需读取,而是每次都会预读,即使只需要一个字节,磁盘也会从这个位置开始,顺序向后读取一定长度的数据放入内存。这样做的理论依据是计算机科学中著名的局部性原理当一个数据被用到时,其附近的数据也通常会马上被使用。程序运行期间所需要的数据通常比较集中。

    由于磁盘顺序读取的效率很高(不需要寻道时间,只需很少的旋转时间),因此对于具有局部性的程序来说,预读可以提高I/O效率。

    预读的长度一般为页(page)的整倍数。页是计算机管理存储器的逻辑块,硬件及操作系统往往将主存和磁盘存储区分割为连续的大小相等的块,每个存储块称为一页(在许多操作系统中,页得大小通常为4k),主存和磁盘以页为单位交换数据。当程序要读取的数据不在主存中时,会触发一个缺页异常,此时系统会向磁盘发出读盘信号,磁盘会找到数据的起始位置并向后连续读取一页或几页载入内存中,然后异常返回,程序继续运行。

    B-/+Tree索引的性能分析

    到这里终于可以分析B-/+Tree索引的性能了。

    上文说过一般使用磁盘I/O次数评价索引结构的优劣。先从B-Tree分析,根据B-Tree的定义,可知检索一次最多需要访问h个节点。数据库系统的设计者巧妙利用了磁盘预读原理,将一个节点的大小设为等于一个页,这样每个节点只需要一次I/O就可以完全载入。为了达到这个目的,在实际实现B-Tree还需要使用如下技巧:

    每次新建节点时,直接申请一个页的空间,这样就保证一个节点物理上也存储在一个页里,加之计算机存储分配都是按页对齐的,就实现了一个node只需一次I/O。

    B-Tree中一次检索最多需要h-1次I/O(根节点常驻内存),渐进复杂度为O(h)=O(logdN)。一般实际应用中,出度d是非常大的数字,通常超过100,因此h非常小(通常不超过3)。

    而红黑树这种结构,h明显要深的多。由于逻辑上很近的节点(父子)物理上可能很远,无法利用局部性,所以红黑树的I/O渐进复杂度也为O(h),效率明显比B-Tree差很多。


    综上所述,用B-Tree作为索引结构效率是非常高的。



    应该花时间学习B-树和B+树数据结构

    =============================================================================================================

    1)B树

    B树中每个节点包含了键值和键值对于的数据对象存放地址指针,所以成功搜索一个对象可以不用到达树的叶节点。

    成功搜索包括节点内搜索和沿某一路径的搜索,成功搜索时间取决于关键码所在的层次以及节点内关键码的数量。

    在B树中查找给定关键字的方法是:首先把根结点取来,在根结点所包含的关键字K1,…,kj查找给定的关键字(可用顺序查找或二分查找法),若找到等于给定值的关键字,则查找成功;否则,一定可以确定要查的关键字在某个Ki或Ki+1之间,于是取Pi所指的下一层索引节点块继续查找,直到找到,或指针Pi为空时查找失败。

    2)B+树

    B+树非叶节点中存放的关键码并不指示数据对象的地址指针,非也节点只是索引部分。所有的叶节点在同一层上,包含了全部关键码和相应数据对象的存放地址指针,且叶节点按关键码从小到大顺序链接。如果实际数据对象按加入的顺序存储而不是按关键码次数存储的话,叶节点的索引必须是稠密索引,若实际数据存储按关键码次序存放的话,叶节点索引时稀疏索引。

    B+树有2个头指针,一个是树的根节点,一个是最小关键码的叶节点。

    所以 B+树有两种搜索方法:

    一种是按叶节点自己拉起的链表顺序搜索。

    一种是从根节点开始搜索,和B树类似,不过如果非叶节点的关键码等于给定值,搜索并不停止,而是继续沿右指针,一直查到叶节点上的关键码。所以无论搜索是否成功,都将走完树的所有层。

    B+ 树中,数据对象的插入和删除仅在叶节点上进行。

    这两种处理索引的数据结构的不同之处:
    a,B树中同一键值不会出现多次,并且它有可能出现在叶结点,也有可能出现在非叶结点中。而B+树的键一定会出现在叶结点中,并且有可能在非叶结点中也有可能重复出现,以维持B+树的平衡。
    b,因为B树键位置不定,且在整个树结构中只出现一次,虽然可以节省存储空间,但使得在插入、删除操作复杂度明显增加。B+树相比来说是一种较好的折中。
    c,B树的查询效率与键在树中的位置有关,最大时间复杂度与B+树相同(在叶结点的时候),最小时间复杂度为1(在根结点的时候)。而B+树的时候复杂度对某建成的树是固定的。


    展开全文
  • 索引排序影响

    万次阅读 2017-03-16 19:47:19
    索引不仅能提高查询速度,还可以添加排序速度,如果order by 后面的语句用到了索引,那么将提高排序的速度。测试1、创建测试表:t15表CREATE TABLE `t15` ( `id` int(10) unsigned NOT NULL AUTO_INCREMENT, `...

    索引不仅能提高查询速度,还可以添加排序速度,如果order by 后面的语句用到了索引,那么将会提高排序的速度。

    测试

    1、创建测试表:t15表

    CREATE TABLE `t15` (
      `id` int(10) unsigned NOT NULL AUTO_INCREMENT,
      `cat_id` int(10) unsigned NOT NULL DEFAULT '0',
      `price` decimal(10,2) NOT NULL DEFAULT '0.00',
      `name` char(5) NOT NULL DEFAULT '',
      PRIMARY KEY (`id`),
    ) ENGINE=InnoDB DEFAULT CHARSET=utf8

    2、插入1W行数据

    <?php  
    $db = 'test';
    $conn = mysql_connect('localhost','root','1234');
    mysql_query('use ' . $db , $conn);
    mysql_query('set names utf8' , $conn);
    
    for($i=1;$i<=10000;$i++) {
        $cat_id = rand(1,10);
        $price = rand(1,50000);
        $name = substr(str_shuffle('abcdefghjkmnpqrstuvwxyzABCDEFGHJKLMNPQRSTUVWXYZ234565789'),0,5);
        $sql = sprintf("insert into t15 values (%d,%d,%f,'%s')",$i,$cat_id,$price,$name);
        mysql_query($sql , $conn);
    }

    3、商场网站,一般都会按照某个分类进行价格上的排序,我们来模拟一下,执行同一条sql语句。

    select name,cat_id,price from t15 where cat_id=1 order by price;

    (1)首先不添加索引

    从查询分析可以看到Extra中使用到了Using filesort,表示需要进行文件排序。
    这里写图片描述

    (2)给(cat_id,price)列添加索引

    alter table t15 add index cp(cat_id,price);

    这里的查询分析中Extra没用了Using filesort,表示添加上索引再进行查询的sql没有使用到外部排序,而是使用到了索引的排序,因为索引本身就是会排序的,所以不需要额外的order by一次。

    这里写图片描述

    4、观测查询时间

    这里写图片描述

    Query_ID为1的是没有添加索引执行的语句,Query_ID为3的是添加索引后执行的语句,一个执行时间为0.013秒,一个执行时间为0.005秒,肯定是加上索引的快,我们来看看具体快在哪里

    Query_ID为1的sql语句执行详细耗时图:
    这里写图片描述

    Query_ID为3的sql语句执行详细耗时图:

    这里写图片描述

    很明显,Query_ID1中的Sorting result耗时0.012秒,而Query_ID2中的Sorting result只耗时0.000004秒,而这个Sorting result就是排序耗时。

    结论:索引对排序的速度是有一定的影响的,所以,在实际的开发中,要结合实际情况制定索引,并尽可能将排序字段添加至索引中。

    展开全文
  • 海量数据处理之数据库索引

    千次阅读 2016-06-06 13:47:54
    前言:本文第一部分讨论数据库的索引及其优化,主要以sql server为例,第二部分我们从Mysql讨论它背后的数据结构和算法原理。 第一部分,数据库索引及其优化 一,什么是索引  数据库索引好比是一本书前面...
     
    

    目录(?)[+]

    前言:本文第一部分讨论数据库的索引及其优化,主要以sql server为例,第二部分我们从Mysql讨论它背后的数据结构和算法原理。

    第一部分,数据库索引及其优化

    一,什么是索引

      数据库索引好比是一本书前面的目录,能加快数据库的查询速度。
      例如这样一个查询:select * from table1 where id=44。如果没有索引,必须遍历整个表,直到ID等于44的这一行被找到为止;有了索引之后(必须是在ID这一列上建立的索引),直接在索引里面找44(也就是在ID这一列找),就可以得知这一行的位置,也就是找到了这一行。可见,索引是用来定位的。
      索引分为聚簇索引和非聚簇索引两种,聚簇索引 是按照数据存放的物理位置为顺序的,而非聚簇索引就不一样了;显然在一个基本表上最多只能建立一个聚簇索引。建立聚簇索引后,更新该索引列上的数据时,往往导致表中记录的物理顺序的变更,代价较大,因此对于经常更新得列不宜建立聚簇索引,聚簇索引能提高多行检索的速度,而非聚簇索引对于单行的检索很快。建立一个聚簇索引如:

    create cluster index id on Student(id);

    二,概述

      建立索引的目的是加快对表中记录的查找或排序。
      为表设置索引要付出代价的:一是增加了数据库的存储空间,二是在插入和修改数据时要花费较多的时间(因为索引也要随之变动)。

    为什么要创建索引

    创建索引可以大大提高系统的性能。

    第一,通过创建唯一性索引,可以保证数据库表中每一行数据的唯一性。
    第二,可以大大加快数据的检索速度,这也是创建索引的最主要的原因。
    第三,可以加速表和表之间的连接,特别是在实现数据的参考完整性方面特别有意义。
    第四,在使用分组和排序子句进行数据检索时,同样可以显著减少查询中分组和排序的时间。
    第五,通过使用索引,可以在查询的过程中,使用优化隐藏器,提高系统的性能。

    也许会有人要问:增加索引有如此多的优点,为什么不对表中的每一个列创建一个索引呢?因为,增加索引也有许多不利的方面。

    第一,创建索引和维护索引要耗费时间,这种时间随着数据量的增加而增加。
    第二,索引需要占物理空间,除了数据表占数据空间之外,每一个索引还要占一定的物理空间,如果要建立聚簇索引,那么需要的空间就会更大。
    第三,当对表中的数据进行增加、删除和修改的时候,索引也要动态的维护,这样就降低了数据的维护速度。

    在哪建索引

    索引是建立在数据库表中的某些列的上面。在创建索引的时候,应该考虑在哪些列上可以创建索引,在哪些列上不能创建索引。一般来说,应该在这些列上创建索引:

    在经常需要搜索的列上,可以加快搜索的速度;
    在作为主键的列上,强制该列的唯一性和组织表中数据的排列结构;
    在经常用在连接的列上,这些列主要是一些外键,可以加快连接的速度;在经常需要根据范围进行搜索的列上创建索引,因为索引已经排序,其指定的范围是连续的;
    在经常需要排序的列上创建索引,因为索引已经排序,这样查询可以利用索引的排序,加快排序查询时间;
    在经常使用在WHERE子句中的列上面创建索引,加快条件的判断速度。

    同样,对于有些列不应该创建索引。一般来说,不应该创建索引的的这些列具有下列特点:

    第一,对于那些在查询中很少使用或者参考的列不应该创建索引。这是因为,既然这些列很少使用到,因此有索引或者无索引,并不能提高查询速度。相反,由于增加了索引,反而降低了系统的维护速度和增大了空间需求。

    第二,对于那些只有很少数据值的列也不应该增加索引。这是因为,由于这些列的取值很少,例如人事表的性别列,在查询的结果中,结果集的数据行占了表中数据行的很大比例,即需要在表中搜索的数据行的比例很大。增加索引,并不能明显加快检索速度。

    第三,对于那些定义为text, image和bit数据类型的列不应该增加索引。这是因为,这些列的数据量要么相当大,要么取值很少,不利于使用索引。

    第四,当修改性能远远大于检索性能时,不应该创建索引。这是因为,修改性能和检索性能是互相矛盾的。当增加索引时,会提高检索性能,但是会降低修改性能。当减少索引时,会提高修改性能,降低检索性能。因此,当修改操作远远多于检索操作时,不应该创建索引。

      精简来说,索引是一种结构.在SQL Server中,索引和表(这里指的是加了聚集索引的表)的存储结构是一样的,都是B树,B树是一种用于查找的平衡多叉树.理解B树的概念如下图:

    理解为什么使用B树作为索引和表(有聚集索引)的结构,首先需要理解SQL Server存储数据的原理.

    在SQL SERVER中,存储的单位最小是页(PAGE),页是不可再分的。就像细胞是生物学中不可再分的,或是原子是化学中不可再分的最小单位一样.这意味着,SQL SERVER对于页的读取,要么整个读取,要么完全不读取,没有折中.

    在数据库检索来说,对于磁盘IO扫描是最消耗时间的.因为磁盘扫描涉及很多物理特性,这些是相当消耗时间的。所以B树设计的初衷是为了减少对于磁盘的扫描次数。如果一个表或索引没有使用B树(对于没有聚集索引的表是使用堆heap存储),那么查找一个数据,需要在整个表包含的数据库页中全盘扫描。这无疑会大大加重IO负担.而在SQL SERVER中使用B树进行存储,则仅仅需要将B树的根节点存入内存,经过几次查找后就可以找到存放所需数据的被叶子节点包含的页!进而避免的全盘扫描从而提高了性能.

    下面,通过一个例子来证明:

    在SQL SERVER中,表上如果没有建立聚集索引,则是按照堆(HEAP)存放的,假设我有这样一张表:

    1

    现在这张表上没有任何索引,也就是以堆存放,我通过在其上加上聚集索引(以B树存放)来展现对IO的减少:

    2

    三、理解聚集索引和非聚集索引


        在SQL SERVER中,最主要的两类索引是聚集索引和非聚集索引。可以看到,这两个分类是围绕聚集这个关键字进行的.那么首先要理解什么是聚集.

        聚集在索引中的定义:

        为了提高某个属性(或属性组)的查询速度,把这个或这些属性(称为聚集码)上具有相同值的元组集中存放在连续的物理块称为聚集。

        简单来说,聚集索引就是:

        3

        在SQL SERVER中,聚集的作用就是将某一列(或是多列)的物理顺序改变为和逻辑顺序相一致,比如,我从adventureworks数据库的employee中抽取5条数据:

        4

        当我在ContactID上建立聚集索引时,再次查询:

        5

        在SQL SERVER中,聚集索引的存储是以B树存储,B树的叶子直接存储聚集索引的数据:

        grid.ai

        因为聚集索引改变的是其所在表的物理存储顺序,所以每个表只能有一个聚集索引.

    非聚集索引

         因为每个表只能有一个聚集索引,如果我们对一个表的查询不仅仅限于在聚集索引上的字段。我们又对聚集索引列之外还有索引的要求,那么就需要非聚集索引了.

         非聚集索引,本质上来说也是聚集索引的一种.非聚集索引并不改变其所在表的物理结构,而是额外生成一个聚集索引的B树结构,但叶子节点是对于其所在表的引用,这个引用分为两种,如果其所在表上没有聚集索引,则引用行号。如果其所在表上已经有了聚集索引,则引用聚集索引的页.

         一个简单的非聚集索引概念如下:

         6

         可以看到,非聚集索引需要额外的空间进行存储,按照被索引列进行聚集索引,并在B树的叶子节点包含指向非聚集索引所在表的指针.

         MSDN中,对于非聚集索引描述图是:

         grid.ai

         可以看到,非聚集索引也是一个B树结构,与聚集索引不同的是,B树的叶子节点存的是指向堆或聚集索引的指针.

         通过非聚集索引的原理可以看出,如果其所在表的物理结构改变后,比如加上或是删除聚集索引,那么所有非聚集索引都需要被重建,这个对于性能的损耗是相当大的。所以最好要先建立聚集索引,再建立对应的非聚集索引.

    聚集索引 VS 非聚集索引


          前面通过对于聚集索引和非聚集索引的原理解释.我们不难发现,大多数情况下,聚集索引的速度比非聚集索引要略快一些.因为聚集索引的B树叶子节点直接存储数据,而聚集索引还需要额外通过叶子节点的指针找到数据.

          还有,对于大量连续数据查找,非聚集索引十分乏力,因为非聚集索引需要在非聚集索引的B树中找到每一行的指针,再去其所在表上找数据,性能因此会大打折扣.有时甚至不如不加非聚集索引.

          因此,大多数情况下聚集索引都要快于非聚集索引。但聚集索引只能有一个,因此选对聚集索引所施加的列对于查询性能提升至关紧要.

    数据库优化

    此外,除了数据库索引之外,在LAMP结果如此流行的今天,数据库(尤其是MySQL)性能优化也是海量数据处理的一个热点。下面就结合自己的经验,聊一聊MySQL数据库优化的几个方面。

    首先,在数据库设计的时候,要能够充分的利用索引带来的性能提升,至于如何建立索引,建立什么样的索引,在哪些字段上建立索引,上面已经讲的很清楚了,这里不在赘述。另外就是设计数据库的原则就是尽可能少的进行数据库写操作(插入,更新,删除等),查询越简单越好。

    其次,配置缓存是必不可少的,配置缓存可以有效的降低数据库查询读取次数,从而缓解数据库服务器压力,达到优化的目的,一定程度上来讲,这算是一个“围魏救赵”的办法。可配置的缓存包括索引缓存(key_buffer),排序缓存(sort_buffer),查询缓存(query_buffer),表描述符缓存(table_cache)。

    第三,切表,切表也是一种比较流行的数据库优化方法。分表包括两种方式:横向分表和纵向分表,其中,横向分表比较有使用意义,故名思议,横向切表就是指把记录分到不同的表中,而每条记录仍旧是完整的(纵向切表后每条记录是不完整的),例如原始表中有100条记录,我要切成2个表,那么最简单也是最常用的方法就是ID取摸切表法,本例中,就把ID为1,3,5,7。。。的记录存在一个表中,ID为2,4,6,8,。。。的记录存在另一张表中。虽然横向切表可以减少查询强度,但是它也破坏了原始表的完整性,如果该表的统计操作比较多,那么就不适合横向切表。横向切表有个非常典型的用法,就是用户数据:每个用户的用户数据一般都比较庞大,但是每个用户数据之间的关系不大,因此这里很适合横向切表。最后,要记住一句话就是:分表会造成查询的负担,因此在数据库设计之初,要想好是否真的适合切表的优化:

    第四,日志分析,在数据库运行了较长一段时间以后,会积累大量的LOG日志,其实这里面的蕴涵的有用的信息量还是很大的。通过分析日志,可以找到系统性能的瓶颈,从而进一步寻找优化方案。

    以上讲的都是单机MySQL的性能优化的一些经验,但是随着信息大爆炸,单机的数据库服务器已经不能满足我们的需求,于是,多多节点,分布式数据库网络出现了,其一般的结构如下:

    分布式数据库结构



     

    展开全文
  • pandas数据清洗,排序索引设置,数据选取

    万次阅读 多人点赞 2017-03-29 21:34:23
    此教程适合有pandas基础的童鞋来看,很多知识点一笔带过,不做详细解释 Pandas数据格式 Series DataFrame:每个column就是一个Series基础属性shape,index,columns,values,dtypes,describe(),head(),tail() 统计...

    此教程适合有pandas基础的童鞋来看,很多知识点会一笔带过,不做详细解释

    Pandas数据格式

    • Series
    • DataFrame:每个column就是一个Series

      基础属性shape,index,columns,values,dtypes,describe(),head(),tail()
      统计属性Series: count(),value_counts(),前者是统计总数,后者统计各自value的总数


    df.isnull() df的空值为True
    df.notnull() df的非空值为True

    • 修改列名
    df.rename(columns = {'key':'key2'},inplace=True)
    
    
    
    • 更改数据格式astype()
    isin                 #计算一个“Series各值是否包含传入的值序列中”的布尔数组
    unique               #返回唯一值的数组
    value_counts         #返回一个Series,其索引为唯一值,值为频率,按计数降序排列

    数据清洗

    • 丢弃值drop()
    df.drop(labels, axis=1)# 按列(axis=1),丢弃指定label的列,默认按行。。。
    • 丢弃缺失值dropna()
    # 默认axi=0(行);1(列),how=‘any’
    df.dropna()#每行只要有空值,就将这行删除
    df.dropna(axis=1)#每列只要有空值,整列丢弃
    df.dropna(how='all')# 一行中全部为NaN的,才丢弃该行
    df.dropna(thresh=3)# 每行至少3个非空值才保留
    • 缺失值填充fillna()
    df.fillna(0)
    df.fillna({1:0,2:0.5}) #对第一列nan值赋0,第二列赋值0.5
    df.fillna(method='ffill') #在列方向上以前一个值作为值赋给NaN
    • 值替换replace()
    # 将df的A列中 -999 全部替换成空值
    df['A'].replace(-999, np.nan)
    #-999和1000 均替换成空值
    obj.replace([-999,1000],  np.nan)
    # -999替换成空值,1000替换成0
    obj.replace([-999,1000],  [np.nan, 0])
    # 同上,写法不同,更清晰
    obj.replace({-999:np.nan, 1000:0})
    • 重复值处理duplicated(),unique(),drop_duplictad()
    df.duplicated()#两行每列完全一样才算重复,后面重复的为True,第一个和不重复的为false,返回true
                   #和false组成的Series类型
    df.duplicated('key')#两行key这一列一样就算重复
    
    df['A'].unique()# 返回唯一值的数组(类型为array)
    
    df.drop_duplicates(['k1'])# 保留k1列中的唯一值的行,默认保留第一行
    df.drop_duplicates(['k1','k2'], take_last=True)# 保留 k1和k2 组合的唯一值的行,take_last=True 保留最后一行

    排序

    • 索引排序
    # 默认axis=0,按行索引对行进行排序;ascending=True,升序排序
    df.sort_index()
    # 按列名对列进行排序,ascending=False 降序
    df.sort_index(axis=1, ascending=False) 
    • 值排序
    # 按值对Series进行排序,使用order(),默认空值会置于尾部
    s = pd.Series([4, 6, np.nan, 2, np.nan])
    s.order()
    
    df.sort_values(by=['a','b'])#按列进行排序
    • 排名
    a=Series([7,-5,7,4,2,0,4])
    a.rank()#默认method='average',升序排名(ascending=True),按行(axis=0)
    #average 值相等时,取排名的平均值
    #min 值相等时,取排名最小值
    #max 值相等时,取排名最大值
    #first值相等时,按原始数据出现顺序排名

    索引设置

    • reindex()
      更新index或者columns,
      默认:更新index,返回一个新的DataFrame
    # 返回一个新的DataFrame,更新index,原来的index会被替代消失
    # 如果dataframe中某个索引值不存在,会自动补上NaN
    df2 = df1.reindex(['a','b','c','d','e'])
    
    # fill_valuse为原先不存在的索引补上默认值,不在是NaN
    df2 = df1.reindex(['a','b','c','d','e'],  fill_value=0)
    
    # inplace=Ture,在DataFrame上修改数据,而不是返回一个新的DataFrame
    df1.reindex(['a','b','c','d','e'],  inplace=Ture)
    
    # reindex不仅可以修改 索引(行),也可以修改列
    states = ["Texas","Utah","California"]
    df2 = df1.reindex( columns=states )
    • set_index()
      将DataFrame中的列columns设置成索引index
      打造层次化索引的方法
    # 将columns中的其中两列:race和sex的值设置索引,race为一级,sex为二级
    # inplace=True 在原数据集上修改的
    adult.set_index(['race','sex'], inplace = True) 
    
    # 默认情况下,设置成索引的列会从DataFrame中移除
    # drop=False将其保留下来
    adult.set_index(['race','sex'], inplace = True) 
    • reset_index()
      将使用set_index()打造的层次化逆向操作
      既是取消层次化索引,将索引变回列,并补上最常规的数字索引
    df.reset_index()

    数据选取

    • []
      只能对行进 行(row/index) 切片,前闭后开df[0:3],df[:4],df[4:]

    • where 布尔查找

     df[df["A"]>7]
    • isin
    # 返回布尔值
    s.isin([1,2,3])
    df['A'].isin([1,2,3])
    df.loc[df['A'].isin([5.8,5.1])]选取列A中值为5.85.1的所有行组成dataframe
    • query
      多个where整合切片,&:于,|:或 
     df.query(" A>5.0 & (B>3.5 | C<1.0) ") 
    • loc :根据名称Label切片
    # df.loc[A,B] A是行范围,B是列范围
    df.loc[1:4,['petal_length','petal_width']]
    
    # 需求1:创建一个新的变量 test
    # 如果sepal_length > 3 test = 1 否则 test = 0
    df.loc[df['sepal_length'] > 6, 'test'] = 1
    df.loc[df['sepal_length'] <=6, 'test'] = 0
    
    # 需求2:创建一个新变量test2 
    # 1.petal_length>2 and petal_width>0.3 = 1 
    # 2.sepeal_length>6 and sepal_width>3 = 2 3.其他 = 0
    df['test2'] = 0
    df.loc[(df['petal_length']>2)&(df['petal_width']>0.3), 'test2'] = 1
    df.loc[(df['sepal_length']>6)&(df['sepal_width']>3), 'test2'] = 2
    • iloc:切位置
    df.iloc[1:4,:]
    • ix:混切
      名称和位置混切,但效率低,少用
    df1.ix[0:3,['sepal_length','petal_width']]
    • map与lambda
    alist = [1,2,3,4]
    map(lambda s : s+1, alist)#map就是将自定义函数应用于Series每个元素
    
    df['sepal_length'].map(lambda s:s*2+1)[0:3]
    • apply和applymap
      apply和applymap是对dataframe的操作,前者操作一行或者一列,后者操作每个元素
    These are techniques to apply function to element, column or dataframe.
    
    Map: It iterates over each element of a series. 
    df[‘column1’].map(lambda x: 10+x), this will add 10 to each element of column1.
    df[‘column2’].map(lambda x: ‘AV’+x), this will concatenate “AV“ at the beginning of each element of column2 (column format is string).
    
    Apply: As the name suggests, applies a function along any axis of the DataFrame.
    df[[‘column1’,’column2’]].apply(sum), it will returns the sum of all the values of column1 and column2.
    df0[['data1']].apply(lambda s:s+1)
    
    ApplyMap: 对dataframe的每一个元素施加一个函数
    func = lambda x: x+2
    df.applymap(func), dataframe每个元素加2 (所有列必须数字类型)
    • contains
    # 使用DataFrame模糊筛选数据(类似SQL中的LIKE)
    # 使用正则表达式进行模糊匹配,*匹配0或无限次,?匹配0或1次
    df_obj[df_obj['套餐'].str.contains(r'.*?语音CDMA.*')] 
    
    # 下面两句效果一致
    df[df['商品名称'].str.contains("四件套")]
    df[df['商品名称'].str.contains(r".*四件套.*")]
    展开全文
  • js之数据字母索引排序

    千次阅读 2019-06-17 17:49:26
    用于通讯录,或者商品列表 1。排序前 ...// 处理数据按字母排序分类。 sortData(data,field){ let letter_reg = /^[A-Z]$/; let list = []; let letter = ''; for (let i = 0; i...
  • MySQL索引的创建与使用

    万次阅读 多人点赞 2018-08-06 18:49:59
    声明:本人主要简单示例MySQL中的单列索引、组合索引的创建与使用索引的创建: 建表时创建: CREATE TABLE 表名( 字段名 数据类型 [完整性约束条件], ……, [UNIQUE | FULLTEXT | SPATIAL] INDEX | KEY ...
  • MySQL索引详解之索引数据结构

    千次阅读 2020-04-21 18:53:22
    前言 很多人对数据库索引可能都是知其然却不知其所以然,对索引没有很深入的理解,在使用过程中也一知半解,导致没有办法准确高效地使用索引,...数据库索引指的是数据库管理系统中一个排序数据结构,以协助快速查...
  • 索引排序

    千次阅读 多人点赞 2014-07-17 00:30:50
    索引排序排序时,若是数据很复杂,对数据的移动显然是费时的。若把数据移动改为指针移动,则减少了操作复杂度。索引排序,也叫地址排序,就是这种排序思想。 索引含义 根据索引的含义不同,索引排序的算法上也...
  • NoSQL——数据索引排序

    千次阅读 2013-12-03 09:52:26
    数据库索引建立在哈希函数,B树和B+树的基础上。 MongoDB MongoDB默认在所包含的所有集合的_id属性上创建一个索引。...Nscanned:被扫描的尸体总数,使用索引时对应索引实体的总数。nscannedOb
  • Oracle 海量数据处理- 索引的选择

    千次阅读 2013-06-29 17:56:19
    应用场景: OLTP 使用比较多,处理键值重复率比较低的字段比较适合使用B-Tree索引处理效率极高。反之当键值重复率很高时,B-Tree索引的效率非常的低效。 在Oracle中主键默认加上B-Tree索引。在Oracle的主键和...
  • mysql索引数据结构

    千次阅读 2020-09-02 18:09:07
    由于 Hash 索引中存放的是经过 Hash 计算之后的 Hash 值,而且Hash值的大小关系并不一定和 Hash 运算前的键值完全一样,所以数据库无法利用索引数据来避免任何排序运算 3.Hash 索引不能利用部分索引键查询 对于...

空空如也

空空如也

1 2 3 4 5 ... 20
收藏数 1,033,226
精华内容 413,290
关键字:

使用索引会影响数据排序