我最近参加了一次有趣的工作面试。在那里我被问到一个关于使用包含长标量列表(即数千个值)的 WHERE..IN 子句优化查询的问题。这个问题不是关于 IN 子句中的子查询,而是关于简单的标量列表。
我马上回答说,这可以使用 INNER JOIN 与另一个表(可能是临时表)进行优化,该表将仅包含那些标量。我的回答被接受了,并且有评论者的注释,“目前没有数据库引擎可以优化长 WHERE..IN 条件以获得足够的性能”。我点了头。
但是当我走出去的时候,我开始有些疑惑了。该条件似乎相当微不足道,并且广泛用于现代 RDBMS 无法对其进行优化。因此,我开始进行一些挖掘。
PostgreSQL:
看来,PostgreSQL parse scalar IN() constructions into ScalarArrayOpExpr structure ,即 sorted .此结构稍后在索引扫描期间用于定位匹配行。此类查询的 EXPLAIN ANALYZE 仅显示一个循环。没有连接完成。所以,我希望这样的查询比 INNER JOIN 更快。我在我现有的数据库上尝试了一些查询,我的测试证明了这一点。但我不关心测试的纯度,而且 Postgres 在 Vagrant 之下,所以我可能是错的。
MSSQL 服务器:
MSSQL 服务器 builds a hash structure from the list of constant expressions and then does a hash join with the source table .尽管似乎没有进行排序,但我认为这是一场性能比赛。我没有做任何测试,因为我没有任何使用此 RDBMS 的经验。
MySQL 服务器:
The 13th of these slides说,在 5.0 之前,这个问题确实在某些情况下发生在 MySQL 中。但除此之外,我没有发现任何其他与错误的 IN () 处理相关的问题。不幸的是,我没有找到任何逆向证明。如果你这样做了,请踢我。
SQLite:
Documentation page暗示了一些问题,但我倾向于相信那里描述的事情确实处于概念层面。没有找到其他信息。
所以,我开始认为我误解了我的面试官或误用了谷歌 ;) 或者,可能是因为我们没有设置任何条件,我们的谈话变得有点含糊(我们没有指定任何具体的 RDBMS或其他条件。那只是抽象的谈话)。
看起来像那些日子,数据库将 IN() 重写为一组 OR 语句(这有时会导致 NULL 出现问题列表中的值,顺便说一句)是很久以前的事了。还是不行?
当然,在标量列表比允许的数据库协议(protocol)数据包长的情况下,INNER JOIN 可能是唯一可用的解决方案。
我认为在某些情况下,查询解析时间(如果没有准备好)本身就会降低性能。
此外,数据库可能无法准备 IN(?) 查询,这将导致一次又一次地重新解析它(这可能会降低性能)。实际上,我从未尝试过,但我认为即使在这种情况下,查询解析和规划与查询执行相比也不是很大。
但除此之外我没有看到其他问题。好吧,除了遇到这个问题之外。如果您有包含数千个 ID 的查询,则说明您的架构有问题。
你呢?
最佳答案
只有在列表上建立索引(最好是主键索引)时,你的答案才是正确的,除非列表真的很小。
任何关于优化的描述都是特定于数据库的。然而,MySQL非常具体地说明了它如何优化 in:
Returns 1 if expr is equal to any of the values in the IN list, else returns 0. If all values are constants, they are evaluated according to the type of expr and sorted. The search for the item then is done using a binary search. This means IN is very quick if the IN value list consists entirely of constants.
在这种情况下,使用 IN 肯定会比使用另一个表更快 -- 并且可能比使用主键索引的另一个表更快。
我认为 SQL Server 将 IN 替换为 OR 的列表。然后这些将作为顺序比较来实现。请注意,如果某些元素比其他元素更常见并且出现在列表的最前面,则顺序比较可能比二进制搜索更快。
关于mysql - 优化 : WHERE x IN (1, 2 .., 100.000) 与 INNER JOIN tmp_table USING(x)?,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/34046927/
文章目录一、概述简介原理模块二、配置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
我看到其他人也遇到过类似的问题,但没有一个解决方案对我有用。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
我已经开始使用mysql2gem。我试图弄清楚一些基本的事情——其中之一是如何明确地执行事务(对于批处理操作,比如多个INSERT/UPDATE查询)。在旧的ruby-mysql中,这是我的方法:client=Mysql.real_connect(...)inserts=["INSERTINTO...","UPDATE..WHEREid=..",#etc]client.autocommit(false)inserts.eachdo|ins|beginclient.query(ins)rescue#handleerrorsorabortentirelyendendclient.commi
1.问题描述使用Python的turtle(海龟绘图)模块提供的函数绘制直线。2.问题分析一幅复杂的图形通常都可以由点、直线、三角形、矩形、平行四边形、圆、椭圆和圆弧等基本图形组成。其中的三角形、矩形、平行四边形又可以由直线组成,而直线又是由两个点确定的。我们使用Python的turtle模块所提供的函数来绘制直线。在使用之前我们先介绍一下turtle模块的相关知识点。turtle模块提供面向对象和面向过程两种形式的海龟绘图基本组件。面向对象的接口类如下:1)TurtleScreen类:定义图形窗口作为绘图海龟的运动场。它的构造器需要一个tkinter.Canvas或ScrolledCanva
我正在尝试绕过rails配置这个极其复杂的迷宫。到目前为止,我设法在ubuntu上设置了rvm(出于某种原因,ruby在ubuntu存储库中已经过时了)。我设法建立了一个Rails项目。我希望我的测试项目使用mysql而不是mysqlite。当我尝试“rakedb:migrate”时,出现错误:“!!!缺少mysql2gem。将其添加到您的Gemfile:gem'mysql2'”当我尝试“geminstallmysql”时,出现错误,告诉我需要为安装命令提供参数。但是,参数列表很大,我不知道该选择哪些。如何通过在ubuntu上运行的rvm和mysql获取rails3?谢谢。
我有一个带有Postgres数据库的Rails应用程序,该数据库有一个带有jsonbgenres列的Artists表。有几十万行。该行中的每个流派列都有一个类似["rock","indie","seenlive","alternative","indierock"]的数组,其中包含不同的流派。我想要做的是在所有行中以JSON格式输出每种类型的计数。类似于:{"rock":532,"powermetal":328,"indie":862}有没有办法有效地做到这一点?更新...这是我目前得到的...genres=Artist.all.pluck(:genres).flatten.delet
我希望Ruby的解析器会进行这种微不足道的优化,但似乎并没有(谈到YARV实现,Ruby1.9.x、2.0.0):require'benchmark'deffib1a,b=0,1whileb由于这两种方法除了在第二种方法中使用预定义常量而不是常量表达式外是相同的,因此Ruby解释器似乎在每个循环中一次又一次地计算幂常数。是否有一些Material说明为什么Ruby根本不进行这种基本优化或只在某些特定情况下进行? 最佳答案 很抱歉给出了另一个答案,但我不想删除或编辑我之前的答案,因为它下面有有趣的讨论。正如JörgWMittag所说,
我正在尝试从数据库中读取大量单元格(超过100.000个)并将它们写入VPSUbuntu服务器上的csv文件。碰巧服务器没有足够的内存。我正在考虑一次读取5000行并将它们写入文件,然后再读取5000行,等等。我应该如何重构我当前的代码以使内存不会被完全消耗?这是我的代码:defwrite_rows(emails)File.open(file_path,"w+")do|f|f该函数由sidekiqworker调用:write_rows(user.emails)感谢您的帮助! 最佳答案 这里的问题是,当您调用emails.each时,
文章目录前言约束硬约束的轨迹优化Corridor-BasedTrajectoryOptimizationBezierCurveOptimizationOtherOptions软约束的轨迹优化Distance-BasedTrajectoryOptimization优化方法前言可以看看我的这几篇Blog1,Blog2,Blog3。上次基于MinimumSnap的轨迹生成,有许多优点,比如:轨迹让机器人可以在某个时间点抵达某个航点。任何一个时刻,都能数学上求出期望的机器人的位置、速度、加速度、导数。MinimumSnap可以把问题转换为凸优化问题。缺点:MnimumSnap可以控制轨迹一定经过中间的
我对为我的RubyonRails3.1.3应用优化我的Unicorn设置的方法很感兴趣。我目前正在高CPU超大实例上生成14个工作进程,因为我的应用程序在负载测试期间似乎受CPU限制。在模拟负载测试中,每秒大约20个请求重放请求,我的实例上的所有8个内核都达到峰值,盒子负载飙升至7-8个。每个unicorn实例使用大约56-60%的CPU。我很好奇可以通过哪些方式对其进行优化?我希望能够每秒将更多请求汇集到这种大小的实例上。内存和所有其他I/O一样完全正常。在我的测试过程中,CPU越来越低。 最佳答案 如果您受CPU限制,您希望使用