jjzjj

mysql - 修改 MySQL 查询以停止将临时表写入磁盘

coder 2023-10-23 原文

我们正在改进站点周围的一些 SQL 查询,并注意到特定 SQL 查询的瓶颈似乎会将结果转储到临时磁盘表中。这很昂贵,当然也非常慢。

我们考虑过将 MySQL 临时目录移至 RAMDISK,但认为我们可以先尝试对其进行优化。

这是转储到磁盘的命令:

select
  d.url,
  d.lid,
  d.title, 
  d.description, 
  d.date, 
  d.hits, 
  d.downloadratingsummary, 
  d.totalvotes, 
  d.totalcomments, 
  d.filesize, 
  d.version, 
  d.homepage, 
  d.ns_compat, 
  d.ns_des_img, 
  t.type
from downloads_downloads d
LEFT JOIN downloads_type t on d.lid = t.lid
where cid=91
ORDER BY FIELD(COALESCE(t.type,-1),1,-1,2,4,5,0,3), date DESC limit 0,20

是否有任何简单的方法来重新组织/修改上述查询以最大限度地减少磁盘上的临时表创建?

虽然我们有使用 MySQL 的经验,但性能优化对我们来说仍然是新事物,因此我们非常感谢任何人可以提供的帮助。

提前感谢您的帮助。

两个引用表的结构

downloads_downloads

索引

下载类型

索引

EXPLAIN 的输出

环境:

OS X 运行 MySQL 5.5.23,内存为 16GB。

最佳答案

我认为这些链接可以帮助优化这个查询:
http://dev.mysql.com/doc/refman/5.5/en/order-by-optimization.html
http://dev.mysql.com/doc/refman/5.5/en/internal-temporary-tables.html

第一个结论 - 无法避免文件排序(临时表),因为 ORDER BY 子句中的查询包含来自两个表的列,并且还包含一个表达式,因此 mySql无法使用索引对其进行优化:

In some cases, MySQL cannot use indexes to resolve the ORDER BY ................
These cases include the following:
- You use ORDER BY with an expression that includes terms other than the key column name
- You are joining many tables, and the columns in the ORDER BY are not all from the first nonconstant table that is used to retrieve rows.


第二个结论 - 因为表包含一个 TEXT 列,所以 MySql 不能使用 modified(优化)的文件排序算法,而必须使用 oryginal 算法.原始算法的一个缺点是它读取表行两次,并以随机方式读取它们,这比顺序读取慢得多:

One problem with this approach is that it reads rows twice: One time when evaluating the WHERE clause, and again after sorting the pair values. And even if the rows were accessed successively the first time (for example, if a table scan is done), the second time they are accessed randomly. (The sort keys are ordered, but the row positions are not.)


第三个结论 - 由于表中包含TEXT列,MySql不能使用内存中的临时表,而必须将其存储在磁盘上:

Some conditions prevent the use of an in-memory temporary table, in which case the server uses an on-disk table instead:
- Presence of a BLOB or TEXT column in the table



考虑到上述情况,将 TEXT 列移动到另一个表中:

create table downloads_description(
  lid int(11) not null unique,
  description text,
  constraint dd_fk foreign key  (lid)
  references downloads_downloads( lid )
);

insert into downloads_description( lid, description )
select lid, description
from downloads_downloads;

alter table downloads_downloads
drop column description;

然后将查询重写为:

SELECT 
  d.url,
  d.lid,
  d.title, 
  dd.description, 
  d.date, 
  d.hits, 
  d.downloadratingsummary, 
  d.totalvotes, 
  d.totalcomments, 
  d.filesize, 
  d.version, 
  d.homepage, 
  d.ns_compat, 
  d.ns_des_img, 
  t.type
FROM downloads_downloads d 
JOIN(
    select   d.lid, t.type
    FROM downloads_downloads d
    LEFT JOIN downloads_type t
    ON d.lid = t.lid
        WHERE cid = 81
    ORDER BY FIELD(COALESCE(t.type,-1),1,-1,2,4,5,0,3), 
          d.date DESC 
    limit 0,20
) t ON d.lid = t.lid
JOIN downloads_description dd
ON dd.lid = d.lid
ORDER BY FIELD(COALESCE(t.type,-1),1,-1,2,4,5,0,3), 
         d.date DESC 
;

关于mysql - 修改 MySQL 查询以停止将临时表写入磁盘,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/18926651/

有关mysql - 修改 MySQL 查询以停止将临时表写入磁盘的更多相关文章

  1. ruby - ECONNRESET (Whois::ConnectionError) - 尝试在 Ruby 中查询 Whois 时出错 - 2

    我正在用Ruby编写一个简单的程序来检查域列表是否被占用。基本上它循环遍历列表,并使用以下函数进行检查。require'rubygems'require'whois'defcheck_domain(domain)c=Whois::Client.newc.query("google.com").available?end程序不断出错(即使我在google.com中进行硬编码),并打印以下消息。鉴于该程序非常简单,我已经没有什么想法了-有什么建议吗?/Library/Ruby/Gems/1.8/gems/whois-2.0.2/lib/whois/server/adapters/base.

  2. Ruby 写入和读取对象到文件 - 2

    好的,所以我的目标是轻松地将一些数据保存到磁盘以备后用。您如何简单地写入然后读取一个对象?所以如果我有一个简单的类classCattr_accessor:a,:bdefinitialize(a,b)@a,@b=a,bendend所以如果我从中非常快地制作一个objobj=C.new("foo","bar")#justgaveitsomerandomvalues然后我可以把它变成一个kindaidstring=obj.to_s#whichreturns""我终于可以将此字符串打印到文件或其他内容中。我的问题是,我该如何再次将这个id变回一个对象?我知道我可以自己挑选信息并制作一个接受该信

  3. ruby-on-rails - 在 Rails 和 ActiveRecord 中查询时忽略某些字段 - 2

    我知道我可以指定某些字段来使用pluck查询数据库。ids=Item.where('due_at但是我想知道,是否有一种方法可以指定我想避免从数据库查询的某些字段。某种反拔?posts=Post.where(published:true).do_not_lookup(:enormous_field) 最佳答案 Model#attribute_names应该返回列/属性数组。您可以排除其中一些并传递给pluck或select方法。像这样:posts=Post.where(published:true).select(Post.attr

  4. 使用canal同步MySQL数据到ES - 2

    文章目录一、概述简介原理模块二、配置Mysql使用版本环境要求1.操作系统2.mysql要求三、配置canal-server离线下载在线下载上传解压修改配置单机配置集群配置分库分表配置1.修改全局配置2.实例配置垂直分库水平分库3.修改group-instance.xml4.启动监听四、配置canal-adapter1修改启动配置2配置映射文件3启动ES数据同步查询所有订阅同步数据同步开关启动4.验证五、配置canal-admin一、概述简介canal是Alibaba旗下的一款开源项目,Java开发。基于数据库增量日志解析,提供增量数据订阅&消费。Git地址:https://github.co

  5. 安卓apk修改(Android反编译apk) - 2

    最近因为项目需要,需要将Android手机系统自带的某个系统软件反编译并更改里面某个资源,并重新打包,签名生成新的自定义的apk,下面我来介绍一下我的实现过程。APK修改,分为以下几步:反编译解包,修改,重打包,修改签名等步骤。安卓apk修改准备工作1.系统配置好JavaJDK环境变量2.需要root权限的手机(针对系统自带apk,其他软件免root)3.Auto-Sign签名工具4.apktool工具安卓apk修改开始反编译本文拿Android系统里面的Settings.apk做demo,具体如何将apk获取出来在此就不过多介绍了,直接进入主题:按键win+R输入cmd,打开命令窗口,并将路

  6. sql - 查询忽略时间戳日期的时间范围 - 2

    我正在尝试查询我的Rails数据库(Postgres)中的购买表,我想查询时间范围。例如,我想知道在所有日期的下午2点到3点之间进行了多少次购买。此表中有一个created_at列,但我不知道如何在不搜索特定日期的情况下完成此操作。我试过:Purchases.where("created_atBETWEEN?and?",Time.now-1.hour,Time.now)但这最终只会搜索今天与那些时间的日期。 最佳答案 您需要使用PostgreSQL'sdate_part/extractfunction从created_at中提取小时

  7. ruby - Ruby 是否使用 $stdout 来写入 puts 和 return 的输出? - 2

    我想知道Ruby用来在命令行打印这些东西的输出流:irb(main):001:0>a="test"=>"test"irb(main):002:0>putsatest=>nilirb(main):003:0>a=>"test"$stdout是否用于irb(main):002:0>和irb(main):003:0>?而且,在这两次调用之间,$stdout的值是否有任何变化?另外,有人能告诉我打印/写入这些内容的Ruby源代码吗? 最佳答案 是的。而且很容易向自己测试/证明。在命令行试试这个:ruby-e'puts"foo"'>test.

  8. Ruby:写入 stdin 并从 stdout 读取? - 2

    我正在编写一个ruby​​程序,它应该执行另一个程序,通过stdin向它传递值,从它的stdout读取响应,然后打印响应。这是我目前所拥有的。#!/usr/bin/envrubyrequire'open3'stdin,stdout,stderr=Open3.popen3('./MyProgram')stdin.puts"helloworld!"output=stdout.readerrors=stderr.readstdin.closestdout.closestderr.closeputs"Output:"puts"-------"putsoutputputs"\nErrors:"p

  9. ruby-on-rails - 无法安装 mysql2 0.3.14 gem - 2

    我看到其他人也遇到过类似的问题,但没有一个解决方案对我有用。0.3.14gem与其他gem文件一起存在。我已经完全按照此处指示完成了所有操作:https://github.com/brianmario/mysql2.我仍然得到以下信息。我不知道为什么安装程序指示它找不到include目录,因为我已经检查过它存在。thread.h文件存在,但不在ruby​​目录中。相反,它在这里:C:\RailsInstaller\DevKit\lib\perl5\5.8\msys\CORE\我正在运行Windows7并尝试在Aptana3中构建我的Rails项目。我的Ruby是1.9.3。$gemin

  10. Ruby -> 写入二维数组 - 2

    我正在处理http://prepwork.appacademy.io/mini-curriculum/array/中概述的数组问题我正在尝试创建函数my_transpose,它接受一个矩阵并返回其转置。我对写入二维数组感到很困惑!这是一个代码片段,突出了我的困惑。rows=[[0,1,2],[3,4,5],[6,7,8]]columns=Array.new(3,Array.new(3))putscolumns.to_s#Outputisa3x3arrayfilledwithnilcolumns[0][0]=0putscolumns.to_s#Outputis[[0,nil,nil],[

随机推荐