精华内容
下载资源
问答
  • 啊啊啊,我的索引用得挺好的啊,就是有Using temporary; Using filesort,查询的结果不是很多到无所谓,要是多了来,就没法玩了。 >>> ....... >>>............. >>>................. >>> 折腾很久之后...

    问题是这样的:有两个表News,Tags,他们的关系是ManyToMany,表如下(django ORM):

    
    class News(models.Model):
        """ news """
        title = models.CharField(max_length=128,verbose_name="新闻标题")
        rank = models.IntegerField(verbose_name="新闻ranking")
        news_time = models.DateField(verbose_name="发布时间")
        publisher = models.CharField(max_length=128,verbose_name="新闻来源")
        news_url = models.URLField(verbose_name="新闻网页链接")
        content = RichTextField(verbose_name="新闻内容")
        hash_digest = models.CharField(max_length=64,verbose_name="哈希摘要",unique=True)
    
    class Tags(models.Model):
        """ tags """
        tag = models.CharField(max_length=32,verbose_name="标签")
        tag_hash = models.CharField(max_length=64,unique=True,verbose_name="标签标示")
        search_times = models.IntegerField(default=0,verbose_name="搜索次数")
        included_items_num = models.IntegerField(default=0,verbose_name="tag所含条目数量")
        news = models.ManyToManyField(News,verbose_name="关联内容")

    然后我想根据tag_hash检索出响应的新闻,说形象点,就是找出含有关键字所对应的新闻,代码大概是这样的:

    News.objects.filter(tags__tag_hash='c13dceabcb143acd6c9298265d618a9f',#`中国` 的 hash
                                    news_time__lte='2016-05-10',
                                    news_time__gte= '2011-09-01'
                                   ).order_by('-news_time','-rank')

    最终生成的sql:

    SELECT
         `news_news`.`id`,
         `news_news`.`title`,
         `news_news`.`rank`,
         `news_news`.`news_time`,
         `news_news`.`content`
    FROM `news_news`
    INNER JOIN `news_tags_news`
    ON ( `news_news`.`id` = `news_tags_news`.`news_id` )
    INNER JOIN `news_tags`
    ON ( `news_tags_news`.`tags_id` = `news_tags`.`id` )
    WHERE (
         `news_tags`.`tag_hash` = 'c13dceabcb143acd6c9298265d618a9f'
          AND `news_news`.`news_time` >= '2011-09-01'
          AND `news_news`.`news_time` <= '2016-05-10'
    )
    ORDER BY `news_news`.`news_time` DESC, `news_news`.`rank` DESC LIMIT 9;

    放到数据库当中查询,slow-query-log中出现:

    ##
    # slow-query.log
    ##
    
    # Time: 160510 11:14:15
    # User@Host: qiulimao[qiulimao] @ [localhost] Id: 114472
    # Query_time: 1.767350 Lock_time: 0.000136 Rows_sent: 9 Rows_examined: 23103
    SET timestamp=1462850055;

    好吧,explain一下:

    *************************** 1. row ***************************
    id: 1
    select_type: SIMPLE
    table: news_tags
    type: const
    possible_keys: PRIMARY,tag_hash
    key: tag_hash
    key_len: 194
    ref: const
    rows: 1
    Extra: Using index; Using temporary; Using filesort
    *************************** 2. row ***************************
    id: 1
    select_type: SIMPLE
    table: news_tags_news
    type: ref
    possible_keys: tags_id,news_tags_news_news_id_index,news_tags_news__tags_id
    key: tags_id
    key_len: 4
    ref: const
    rows: 6232
    Extra: Using index
    *************************** 3. row ***************************
    id: 1
    select_type: SIMPLE
    table: news_news
    type: eq_ref
    possible_keys: PRIMARY,search_result_index
    key: PRIMARY
    key_len: 4
    ref: news.news_tags_news.news_id
    rows: 1
    Extra: Using where
    3 rows in set (0.00 sec)

    啊啊啊,我的索引用得挺好的啊,就是有Using temporary; Using filesort,查询的结果不是很多到无所谓,要是多了来,就没法玩了。

    >>> .......

    >>>.............

    >>>.................

    >>> 折腾很久之后:

    最终,除了不用排序之外,我真的想不出什么能够消除filesort的方法了.........

    看看大家能不能支招,

    目前我有的思路是:做子查询

    select news_table.id,
    news_table.news_time
    FROM
        (select
             news_news.id,
             news_news.news_time
             from news_news
             order by news_time desc,rank desc)
    as news_table 
    INNER JOIN `news_tags_news`
    ON ( `news_table`.`id` = `news_tags_news`.`news_id` )
    INNER JOIN `news_tags`
    ON ( `news_tags_news`.`tags_id` = `news_tags`.`id` )
    WHERE (
         `news_tags`.`tag_hash` = 'a4ce03da95bb1b3da0dc0629e20563ec'
          AND `news_table`.`news_time` >= '2011-09-01'
          AND `news_table`.`news_time` <= '2016-05-10'
    );
    1. 子查询:在subquery里面就把news的顺序拍好,但是在django当中不好实现,django中__in并不好实现,.extra即将不被支持,sql大概是这样写的: 
    2. 在mysql上做文章:创建一个已经排好序的view,但是要在django当中操作起来不是那么简单。

     

    请DBA,django大神们支招............

    转载于:https://my.oschina.net/b1ack2ephyr/blog/672917

    展开全文
  • Using temporary; Using filesort *************************** 2. row *************************** id: 1 select_type: SIMPLE table: news_tags_news type: ref possible_keys: tags_id,news_tags_news_news_id_...

    问题是这样的:有两个表News,Tags,他们的关系是ManyToMany,表如下(django ORM):

    class News(models.Model):

    """ news """

    title = models.CharField(max_length=128,verbose_name="新闻标题")

    rank = models.IntegerField(verbose_name="新闻ranking")

    news_time = models.DateField(verbose_name="发布时间")

    publisher = models.CharField(max_length=128,verbose_name="新闻来源")

    news_url = models.URLField(verbose_name="新闻网页链接")

    content = RichTextField(verbose_name="新闻内容")

    hash_digest = models.CharField(max_length=64,verbose_name="哈希摘要",unique=True)

    class Tags(models.Model):

    """ tags """

    tag = models.CharField(max_length=32,verbose_name="标签")

    tag_hash = models.CharField(max_length=64,unique=True,verbose_name="标签标示")

    search_times = models.IntegerField(default=0,verbose_name="搜索次数")

    included_items_num = models.IntegerField(default=0,verbose_name="tag所含条目数量")

    news = models.ManyToManyField(News,verbose_name="关联内容")

    然后我想根据tag_hash检索出响应的新闻,说形象点,就是找出含有关键字所对应的新闻,代码大概是这样的:

    News.objects.filter(tags__tag_hash='c13dceabcb143acd6c9298265d618a9f',#`中国` 的 hash

    news_time__lte='2016-05-10',

    news_time__gte= '2011-09-01'

    ).order_by('-news_time','-rank')

    最终生成的sql:

    SELECT

    `news_news`.`id`,

    `news_news`.`title`,

    `news_news`.`rank`,

    `news_news`.`news_time`,

    `news_news`.`content`

    FROM `news_news`

    INNER JOIN `news_tags_news`

    ON ( `news_news`.`id` = `news_tags_news`.`news_id` )

    INNER JOIN `news_tags`

    ON ( `news_tags_news`.`tags_id` = `news_tags`.`id` )

    WHERE (

    `news_tags`.`tag_hash` = 'c13dceabcb143acd6c9298265d618a9f'

    AND `news_news`.`news_time` >= '2011-09-01'

    AND `news_news`.`news_time` <= '2016-05-10'

    )

    ORDER BY `news_news`.`news_time` DESC, `news_news`.`rank` DESC LIMIT 9;

    放到数据库当中查询,slow-query-log中出现:

    ##

    # slow-query.log

    ##

    # Time: 160510 11:14:15

    # User@Host: qiulimao[qiulimao] @ [localhost] Id: 114472

    # Query_time: 1.767350 Lock_time: 0.000136 Rows_sent: 9 Rows_examined: 23103

    SET timestamp=1462850055;

    好吧,explain一下:

    *************************** 1. row ***************************

    id: 1

    select_type: SIMPLE

    table: news_tags

    type: const

    possible_keys: PRIMARY,tag_hash

    key: tag_hash

    key_len: 194

    ref: const

    rows: 1

    Extra: Using index; Using temporary; Using filesort

    *************************** 2. row ***************************

    id: 1

    select_type: SIMPLE

    table: news_tags_news

    type: ref

    possible_keys: tags_id,news_tags_news_news_id_index,news_tags_news__tags_id

    key: tags_id

    key_len: 4

    ref: const

    rows: 6232

    Extra: Using index

    *************************** 3. row ***************************

    id: 1

    select_type: SIMPLE

    table: news_news

    type: eq_ref

    possible_keys: PRIMARY,search_result_index

    key: PRIMARY

    key_len: 4

    ref: news.news_tags_news.news_id

    rows: 1

    Extra: Using where

    3 rows in set (0.00 sec)

    啊啊啊,我的索引用得挺好的啊,就是有Using temporary; Using filesort,查询的结果不是很多到无所谓,要是多了来,就没法玩了。

    >>> .......

    >>>.............

    >>>.................

    >>> 折腾很久之后:

    最终,除了不用排序之外,我真的想不出什么能够消除filesort的方法了.........

    看看大家能不能支招,

    目前我有的思路是:做子查询

    select news_table.id,

    news_table.news_time

    FROM

    (select

    news_news.id,

    news_news.news_time

    from news_news

    order by news_time desc,rank desc)

    as news_table

    INNER JOIN `news_tags_news`

    ON ( `news_table`.`id` = `news_tags_news`.`news_id` )

    INNER JOIN `news_tags`

    ON ( `news_tags_news`.`tags_id` = `news_tags`.`id` )

    WHERE (

    `news_tags`.`tag_hash` = 'a4ce03da95bb1b3da0dc0629e20563ec'

    AND `news_table`.`news_time` >= '2011-09-01'

    AND `news_table`.`news_time` <= '2016-05-10'

    );

    子查询:在subquery里面就把news的顺序拍好,但是在django当中不好实现,django中__in并不好实现,.extra即将不被支持,sql大概是这样写的:

    在mysql上做文章:创建一个已经排好序的view,但是要在django当中操作起来不是那么简单。

    请DBA,django大神们支招............

    展开全文
  • Using temporaryUsing filesort

    万次阅读 2019-06-13 23:35:26
    通过explain查看sql的执行计划时,... Using filesort,其中此次重点关注Using temporary; Using filesort。 Using temporary Using temporary表示由于排序没有走索引、使用union、子查询连接查询、使用某些视图等...

    通过explain查看sql的执行计划时,Extra字段的值往往会看到Using where; Using index; Using temporary; Using filesort,其中此次重点关注Using temporary; Using filesort

    Using temporary

    Using temporary表示由于排序没有走索引、使用union、子查询连接查询、使用某些视图等原因(详见internal-temporary-tables),因此创建了一个内部临时表。注意这里的临时表可能是内存上的临时表,也有可能是硬盘上的临时表,理所当然基于内存的临时表的时间消耗肯定要比基于硬盘的临时表的实际消耗小。

    查看sql执行时使用的是内存临时表还是硬盘临时表,需要使用如下命令:

    mysql> show global status like '%tmp%';
    +-------------------------+-------+
    | Variable_name           | Value |
    +-------------------------+-------+
    | Created_tmp_disk_tables | 0     |
    | Created_tmp_files       | 5     |
    | Created_tmp_tables      | 11    |
    +-------------------------+-------+
    3 rows in set
    

    Created_tmp_tables表示mysql创建的内部临时表的总数(包括内存临时表和硬盘临时表);Created_tmp_disk_tables表示mysql创建的硬盘临时表的总数。

    当mysql需要创建临时表时,选择内存临时表还是硬盘临时表取决于参数tmp_table_sizemax_heap_table_size,内存临时表的最大容量为tmp_table_sizemax_heap_table_size值的最小值,当所需临时表的容量大于两者的最小值时,mysql就会使用硬盘临时表存放数据。

    用户可以在mysql的配置文件里修改该两个参数的值,两者的默认值均为16M。

    tmp_table_size = 16M
    max_heap_table_size = 16M
    

    查看tmp_table_sizemax_heap_table_size值:

    mysql> show global variables like 'max_heap_table_size';
    +---------------------+----------+
    | Variable_name       | Value    |
    +---------------------+----------+
    | max_heap_table_size | 16777216 |
    +---------------------+----------+
    1 row in set
    
    mysql> show global variables like 'tmp_table_size';
    +----------------+----------+
    | Variable_name  | Value    |
    +----------------+----------+
    | tmp_table_size | 16777216 |
    +----------------+----------+
    1 row in set
    

    Using filesort

    如果问Using filesort是什么意思,大多数人应该会回答“基于硬盘的排序”或者“数据太多不适合内存,所以在硬盘上排序”。然而这些解释是错误的。

    Using filesort仅仅表示没有使用索引的排序,事实上filesort这个名字很糟糕,并不意味着在硬盘上排序,filesort与文件无关。因此消除Using filesort的方法就是让查询sql的排序走索引。

    filesort使用的算法是QuickSort,即对需要排序的记录生成元数据进行分块排序,然后再使用mergesort方法合并块。其中filesort可以使用的内存空间大小为参数sort_buffer_size的值,默认为2M。当排序记录太多sort_buffer_size不够用时,mysql会使用临时文件来存放各个分块,然后各个分块排序后再多次合并分块最终全局完成排序。

    mysql> show global variables like 'sort_buffer_size';
    +------------------+--------+
    | Variable_name    | Value  |
    +------------------+--------+
    | sort_buffer_size | 262144 |
    +------------------+--------+
    1 row in set
    

    Sort_merge_passes表示filesort执行过的文件分块合并次数的总和,如果该值比较大,建议增大sort_buffer_size的值。

    mysql> show global status like '%sort%';
    +-------------------+---------+
    | Variable_name     | Value   |
    +-------------------+---------+
    | Sort_merge_passes | 226     |
    | Sort_range        | 0       |
    | Sort_rows         | 1384911 |
    | Sort_scan         | 6       |
    +-------------------+---------+
    4 rows in set
    

    filesort排序方式

    filesort使用的排序方法有两种:

    第一种方法是对需要排序的记录生成<sort_key,rowid>的元数据进行排序,该元数据仅包含排序字段和rowid。排序完成后只有按字段排序的rowid,因此还需要通过rowid进行回表操作获取所需要的列的值,可能会导致大量的随机IO读消耗;

    第二种方法是是对需要排序的记录生成<sort_key,additional_fields>的元数据,该元数据包含排序字段和需要返回的所有列。排序完后不需要回表,但是元数据要比第一种方法长得多,需要更多的空间用于排序。

    参数max_length_for_sort_data字段用于控制filesort使用的排序方法,当所有需要排序记录的字段数量总和小于max_length_for_sort_data时使用第二种算法,否则会用第一种算法。该值的默认值为1024。

    mysql> show global variables like 'max_length_for_sort_data';
    +--------------------------+-------+
    | Variable_name            | Value |
    +--------------------------+-------+
    | max_length_for_sort_data | 1024  |
    +--------------------------+-------+
    1 row in set
    
    mysql> set global max_length_for_sort_data = 1024;
    
    展开全文
  • 通过explain查看sql的执行计划时,... Using filesort,其中此次重点关注Using temporary; Using filesort。 Using temporary Using temporary表示由于排序没有走索引、使用union、子查询连接查询、使用某些视...

    通过explain查看sql的执行计划时,Extra字段的值往往会看到Using where; Using index; Using temporary; Using filesort,其中此次重点关注Using temporary; Using filesort。

    Using temporary


    Using temporary表示由于排序没有走索引、使用union、子查询连接查询、使用某些视图等原因(详见internal-temporary-tables),因此创建了一个内部临时表。注意这里的临时表可能是内存上的临时表,也有可能是硬盘上的临时表,理所当然基于内存的临时表的时间消耗肯定要比基于硬盘的临时表的实际消耗小。

    查看sql执行时使用的是内存临时表还是硬盘临时表,需要使用如下命令:

    mysql> show global status like '%tmp%';
    +-------------------------+-------+
    | Variable_name           | Value |
    +-------------------------+-------+
    | Created_tmp_disk_tables | 0     |
    | Created_tmp_files       | 5     |
    | Created_tmp_tables      | 11    |
    +-------------------------+-------+
    3 rows in set

    Created_tmp_tables表示mysql创建的内部临时表的总数(包括内存临时表和硬盘临时表);Created_tmp_disk_tables表示mysql创建的硬盘临时表的总数。

    当mysql需要创建临时表时,选择内存临时表还是硬盘临时表取决于参数tmp_table_size和max_heap_table_size,内存临时表的最大容量为tmp_table_size和max_heap_table_size值的最小值,当所需临时表的容量大于两者的最小值时,mysql就会使用硬盘临时表存放数据。

    用户可以在mysql的配置文件里修改该两个参数的值,两者的默认值均为16M。

    tmp_table_size = 16M
    max_heap_table_size = 16M
    1
    2
    查看tmp_table_size和max_heap_table_size值:

    mysql> show global variables like 'max_heap_table_size';
    +---------------------+----------+
    | Variable_name       | Value    |
    +---------------------+----------+
    | max_heap_table_size | 16777216 |
    +---------------------+----------+
    1 row in set

    mysql> show global variables like 'tmp_table_size';
    +----------------+----------+
    | Variable_name  | Value    |
    +----------------+----------+
    | tmp_table_size | 16777216 |
    +----------------+----------+
    1 row in set


    Using filesort


    如果问Using filesort是什么意思,大多数人应该会回答“基于硬盘的排序”或者“数据太多不适合内存,所以在硬盘上排序”。然而这些解释是错误的。

    Using filesort仅仅表示没有使用索引的排序,事实上filesort这个名字很糟糕,并不意味着在硬盘上排序,filesort与文件无关。因此消除Using filesort的方法就是让查询sql的排序走索引。

    filesort使用的算法是QuickSort,即对需要排序的记录生成元数据进行分块排序,然后再使用mergesort方法合并块。其中filesort可以使用的内存空间大小为参数sort_buffer_size的值,默认为2M。当排序记录太多sort_buffer_size不够用时,mysql会使用临时文件来存放各个分块,然后各个分块排序后再多次合并分块最终全局完成排序。

    mysql> show global variables like 'sort_buffer_size';
    +------------------+--------+
    | Variable_name    | Value  |
    +------------------+--------+
    | sort_buffer_size | 262144 |
    +------------------+--------+
    1 row in set

    Sort_merge_passes表示filesort执行过的文件分块合并次数的总和,如果该值比较大,建议增大sort_buffer_size的值。

    mysql> show global status like '%sort%';
    +-------------------+---------+
    | Variable_name     | Value   |
    +-------------------+---------+
    | Sort_merge_passes | 226     |
    | Sort_range        | 0       |
    | Sort_rows         | 1384911 |
    | Sort_scan         | 6       |
    +-------------------+---------+
    4 rows in set

    filesort排序方式
    filesort使用的排序方法有两种:

    第一种方法是对需要排序的记录生成<sort_key,rowid>的元数据进行排序,该元数据仅包含排序字段和rowid。排序完成后只有按字段排序的rowid,因此还需要通过rowid进行回表操作获取所需要的列的值,可能会导致大量的随机IO读消耗;

    第二种方法是是对需要排序的记录生成<sort_key,additional_fields>的元数据,该元数据包含排序字段和需要返回的所有列。排序完后不需要回表,但是元数据要比第一种方法长得多,需要更多的空间用于排序。

    参数max_length_for_sort_data字段用于控制filesort使用的排序方法,当所有需要排序记录的字段数量总和小于max_length_for_sort_data时使用第二种算法,否则会用第一种算法。该值的默认值为1024。

    mysql> show global variables like 'max_length_for_sort_data';
    +--------------------------+-------+
    | Variable_name            | Value |
    +--------------------------+-------+
    | max_length_for_sort_data | 1024  |
    +--------------------------+-------+
    1 row in set

    mysql> set global max_length_for_sort_data = 1024;
    1

     

    展开全文
  • Using temporaryUsing filesort分析mysql>showcreatetablet1;+-------+----------------------------------|Table|CreateTable+-------+--------------------------------|t1|CREATETABLE`t1`(`i...
  • Using temporary; Using filesort | | 1 | SIMPLE | t2 | ALL | NULL | NULL | NULL | NULL | 1 | Using where; Using join buffer | +----+-------------+-------+------+---------------+------+---------+------...
  • 多表关联时,在order by中使用了非驱动表字段进行排序,会出现Using temporary; Using filesort,此时需要优化。 mysql会自动将数据量较小的表设置为驱动表,但是我们排序的字段又不是该表的字段,使用left join,...
  • Using temporary; Using filesort | +----+-------------+--------------+-------+---------------+---------+---------+------+------+----------------------------------------------+ 1 row in set (0.00 sec) ...
  • Mysql-explain之Using temporaryUsing filesort解决方案
  • 在使用explain优化sql的时候,有Using temporary; Using filesort这两种是需要特别注意的: Using temporary:在MySQL执行查询的过程中自动产生临时表(Creating tmp table) Using filesort:是指查询完成之前...
  • using filesort一般人的回答是: “当行数据太大,导致内存无法容下这些数据产生的临时表时,他们就会被放入磁盘中排序。” 很不幸,这个答案是错的 ,临时表在太大的时候确实会到磁盘离去,但是EXPLAIN不会显示这些...
  • 解释一: These are the following conditions under which temporary tables are created. UNION queries use temporary tables...Some views require temporary tables, such those evaluated using the TEMPTABLE...
  • mysql使用roll up后sql出现Using temporary; Using filesort,怎么优化啊
  • | 1 | SIMPLE | t1 | ALL | NULL | NULL | NULL | NULL | 9 | Using filesort | +----+-------------+-------+------+---------------+------+---------+------+------+----------------+ 1 ...
  • 一、什么是Using temporary ; Using filesort1. using filesortfilesort主要用于查询数据结果集的排序操作,首先MySQL会使用sort_buffer_size大小的内存进行排序,如果结果集超过了sort_buffer_size大小,会把这一个...
  • Using filsort文档中的解释: Mysql需要额外的一次传递,以找出如何按排序顺序检索行,通过根据联接类型浏览所有行并为所有匹配where子句的行保存排序关键字和行的指针来完成排序,然后关键字被排序,并按排序顺序...

空空如也

空空如也

1 2 3 4 5 ... 20
收藏数 8,411
精华内容 3,364
关键字:

temporaryusing