zoukankan      html  css  js  c++  java
  • 大数据表的查询优化方案

    假设有一张大表。表中的数据有几百万、几千万甚至上亿。要实现实时查询,查询的结果要在十秒钟之内出来。怎么办?怎样做优化?

    本人如今做的项目中,有个表的数据超过1千万行,超过3G的数据。如今须要对表中的数据进行查询统计,之前因为没做优化,导致此表的查询效率很低下,让使用者很苦恼,于是本人參与了此表的优化。

    举个类似的样例。比方表中的结构例如以下,如今要统计某一天出生的人口数,或者统计某一城市的人口数。或者某一城市某一天出生的人口数。

    CREATE TABLE `population` (
      `population_id` bigint(64) NOT NULL AUTO_INCREMENT COMMENT '人口表',
      `name` varchar(128) COLLATE utf8_bin DEFAULT NULL COMMENT '姓名',
      `city` varchar(32) COLLATE utf8_bin DEFAULT NULL COMMENT '城市',
      `birthday` date DEFAULT NULL COMMENT '出生日期', 
      PRIMARY KEY (`population_id`)
    )
    
    查询某一城市某一天出生的人口数
    SELECT COUNT(*) FROM population WHERE city='广州' AND birthday = '2014-11-02'
    查询某一城市的人口数
    SELECT COUNT(*) FROM population WHERE city='广州' 
    查询某一天出生的人口数
    SELECT COUNT(*) FROM population WHERE birthday = '2014-11-02'
    

    提出了两个优化方案,

    (1).优化索引

        通过加入索引后,查询的效率得到极大的提升,经常使用查询的查询时间从原来的几十秒下降到几秒。

        建立下面两个单列索引

    ALTER TABLE `population`   
      ADD  INDEX `fk_city` (`city`),
      ADD  INDEX `fk_birthday` (`birthday`);
    

       也能够建立下面两个组合索引

    ALTER TABLE `population`   
      ADD  INDEX `fk_index1` (`city`, `birthday`),
      ADD  INDEX `fk_index2` (`birthday`, `city`);
    

    (2).使用中间表
        尽管索引优化能够将查询时间大大降低,但假设数据量达到一定量时,有些情况下索引到的数据达到几百万时,查询仍然会非常慢,因此索引优化无法从根本上解决这个问题。如今表中的数据量越来越大,平均每一个月要添加一两百万的数据,索引的优化方法仅仅是临时的。仅仅能解决小数据量的查询问题。随着数据量的高速增长,索引带来的性能优化非常easy达到极限。要寻找其它的解决方式。

         我们依据业务需求的特点,创建中间表population_statistics,将表population中的统计数据存放到中间表population_statistics中,查询时直接从中间表population_statistics中查询。注意。在对表population进行增、删、改时,必须同一时候更新population_statistics中的数据,否则会出现数据不一致的错误。

    CREATE TABLE `population_statistics` (
      `population_statistics_id` bigint(64) NOT NULL AUTO_INCREMENT COMMENT '人口统计表ID',
      `city` varchar(128) COLLATE utf8_bin DEFAULT NULL COMMENT '城市',
      `birthday` int(32) DEFAULT NULL COMMENT '出生日期',
      `total_count` int(32) DEFAULT NULL COMMENT '人口数量',
      PRIMARY KEY (`population_statistics_id`),
      KEY `fk_city` (`city`),
      KEY `fk_birthday` (`birthday`)
    )
    查询某一城市某一天出生的人口数
    SELECT total_count FROM population_statistics WHERE city='广州' AND birthday = '2014-11-02';
    查询某一城市的人口数
    SELECT COUNT(total_count) FROM population_statistics WHERE city='广州';
    查询某一天出生的人口数
    SELECT COUNT(total_count) FROM population_statistics WHERE birthday = '2014-11-02';
    

       某个城市某一天的人口在表population中可能有几千甚至万的数据,而在统计表population_statistics中最多仅仅有一条数据。也就是说统计表population_statistics中的数据量仅仅有人口表population的几千分之中的一个,再加上索引的优化,查询的速度会极大提高。

    以下总结一下经常使用的大数据表优化方案.

    1. 索引优化

    通过建立合理高效的索引,提高查询的速度.

    建议阅读本人写的一篇关于索引的博客

    http://blog.csdn.net/brushli/article/details/39677387

    2. SQL优化

    组织优化SQL语句,使查询效率达到最优,在非常多情况下要考虑索引的作用.

    建议阅读考本人写的一篇关于索引的博客

    http://blog.csdn.net/brushli/article/details/39677387

    3. 水平拆表

    假设表中的数据呈现出某一类特性,比方呈现时间特性,那么能够依据时间段将表拆分成多个。

    比方按年划分、按季度划分、按月划分等等。查询时按时间段进行拆分查询,再把查询结果进行合并;

    比方按地区将表拆分,不同地区的数据放在不同的表里面,然后对查询进行分拆,对查询结果进行合并。

    4. 垂直拆表

    将表按字段拆分成多个表,经常使用的字段放在一个表,不经常使用的字段或大字段放在另外一个表。因为数据库每次查询都是以块为单位,而每块的容量是有限的。一般是十几K或几十K。将表按字段拆分后,单次IO所能检索到的行数一般会提高非常多。查询效率就能提高上去。

    比方有成员表。结构例如以下:

    CREATE TABLE `member` (
      `member_id` bigint(64) NOT NULL AUTO_INCREMENT COMMENT '成员表ID',
      `name` varchar(128) COLLATE utf8_bin DEFAULT NULL COMMENT '成员姓名',
      `age` int(32) DEFAULT NULL COMMENT '成员年龄',
      `introduction` text COLLATE utf8_bin COMMENT '成员介绍',
      PRIMARY KEY (`member_id`)
    )
    

    introduction是大字段,保存成员的介绍,这个大字段会严重影响查询效率,能够将它独立出来,单独形成一个表。

    CREATE TABLE `member` (
      `member_id` bigint(64) NOT NULL AUTO_INCREMENT COMMENT '成员表ID',
      `name` varchar(128) COLLATE utf8_bin DEFAULT NULL COMMENT '成员姓名',
      `age` int(32) DEFAULT NULL COMMENT '成员年龄',
      PRIMARY KEY (`member_id`)
    )
    
    CREATE TABLE `member_introduction` (
      `member_introduction_id` bigint(64) NOT NULL AUTO_INCREMENT COMMENT '成员介绍表ID',
      `member_id` bigint(64) DEFAULT NULL COMMENT '成员ID',
      `introduction` text COLLATE utf8_bin COMMENT '成员介绍',
      PRIMARY KEY (`member_introduction_id`),
      KEY `fk_member_id` (`member_id`),
      CONSTRAINT `fk_member_id` FOREIGN KEY (`member_id`) REFERENCES `member` (`member_id`)
    )
    

    5. 建立中间表,以空间换时间

    在有些情况下。是能够通过建立中间表来加快查询速度的。详情可看文章开头的样例。

    6. 用内存缓存数据。以空间换时间

    将经常使用并且不常改动的数据载入到内存中,直接从内存查询则可。

    能够使用热门的缓存技术,如Memcache、Redis、Ehcache等。

    7.    使用其它辅助技术

    Solr:一种基于Lucene的JAVA搜索引擎技术

  • 相关阅读:
    React-Native到0.44版本后Navigator 不能用的问题
    php基础
    数据库学习内容复习
    数据库常用的函数
    45道题 数据库的
    数据库里any 和 all 的区别
    高级查询
    表中添加列,删除列,修改列名字
    创建,读取,修改,删除表 简单查询 12种
    设计表:多张表存储学生成绩及各种信息
  • 原文地址:https://www.cnblogs.com/wgwyanfs/p/6732934.html
Copyright © 2011-2022 走看看