转换绝对索引的函数是什么意思呢?

1.到底什么是Python?你可以在回答中与其他技术进行对比

Python是一种解释型语言。这就是说,与C语言和C的衍生语言不同,Python代码在运行之前不需要编译。其他解释型语言还包括PHP和Ruby。Python是动态类型语言,指的是你在声明变量时,不需要说明变量的类型。你可以直接编写类似x=111和x="I'm a string"这样的代码,程序不会报错。Python非常适合面向对象的编程(OOP),因为它支持通过组合(composition)与继承(inheritance)的方式定义类(class)。
Python中没有访问修饰符(access specifier,类似C++中的public和private),但以__XX(双横线)结尾的函数或者变量相当于private。这么设计的依据是“大家都是成年人了”,Python本身没有任何机制阻止你干坏事,一切全靠自觉。
objects)。这指的是它们可以被指定给变量,函数既能返回函数类型,也可以接受函数作为输入。类(class)也是第一类对象。Python代码编写快,但是运行速度比编译语言通常要慢。好在Python允许加入基于C语言编写的扩展,因此我们能够优化代码,消除瓶颈,这点通常是可以实现的。Numpy就是一个很好的例子,它的运行速度真的非常快,因为很多算术运算其实并不是通过Python实现的。
Python用途非常广泛——网络应用,自动化,科学建模,大数据应用,等等。它也常被用作“胶水语言”,帮助其他语言和组件改善运行状况。Python让困难的事情变得容易,因此程序员可以专注于算法和数据结构的设计,而不用处理底层的细节。
如果你应聘的是一个Python开发岗位,你就应该知道这是门什么样的语言,以及它为什么这么酷。以及它哪里不好。

PEP8是一个编程规范,内容是一些关于如何让你的程序更具可读性的建议。
其主要内容包括代码编排、文档编排、空格的使用、注释、文档描述、命名规范、编码建议等。

Pickle模块读入任何Python对象,将它们转换成字符串,然后使用dump函数将其转储到一个文件中,这个过程叫做pickling。反之从存储的字符串文件中提取原始Python对象的过程,叫做unpickling。

4.说说python程序运行过程?

迄今为止,我们大多数将 python 作为一门编程语言来介绍,但从实现来看,python 也是一个名为解释器的软件包。解释器是一个让其他程序运行起来的程序。当你编写了一段python程序后,python解释器将读取程序,并按照其中的命令执行,得出结果。 实际上,解释器是代码与机器硬件之间的软件逻辑层。

按照惯例,python是以.py结尾的。从技术上讲,这种命名方案在导入时才是必须的,你可以用任何自己喜欢的文本编辑器创建以其它扩展名结尾的文件,但大多数python文件为了统一都是以.py结尾命名的。你在文本文件中输入代码,之后在解释器中运行这些代码。

执行程序时,python内部(对大多数用户完全隐藏)会先将源代码编译成字节码。编译是一个简单的翻译步骤,字节码是一个低级的与平台无关的表现形式。这些字节码比文本文件中的源代码语句的运行速度快的多。如果python进程在机器上具有写入权限,那么它会将字节码保存在一个以.pyc为扩展名的文件中。python保存字节码是对启动速度的一个优化。如果下次启动时,源代码没有修改,并且使用的python版本也没有改变,那么python将会直接加载.pyc文件,并跳过编译这个步骤。如果python无法在机器上写入字节码,程序仍然可以工作:字节码会在内存中生成,并在程序结束时被丢弃。

一旦程序被编译成字节码,之后的字节码发送到python虚拟机(Python Virtual Machine,PVM)上来执行。PVM就是迭代运行字节码指令的一个大循环,一个接一个地完成操作。PVM是Python运行时的引擎,它时常表现为Python系统的一部分,并且是实际运行脚本的组件。从技术上来说,它只是所谓Python解释器的最后一步。
整理自python学习手册第五版,阅读书籍以了解更多细节

5.Python是怎样管理内存的?

Python的内存管理是由私有heap空间管理的。所有的Python对象和数据结构都在一个私有heap中。程序员没有访问该heap的权限,只有解释器才能对它进行操作。
Python的heap空间分配内存是由Python的内存管理模块进行的,其核心API会提供一些访问该模块的方法供程序员使用。
Python有自带的垃圾回收系统,它回收并释放没有被使用的内存,让它们能够被其他程序使用。

Linux 允许将命令执行结果重定向到一个文件,将本应显示在终端上的内容输出/追加到指定文件中:

表示输出,会覆盖文件原有的内容

表示追加,会将内容追加到已有文件的末尾

7.python为什么不能像C++一样快?如果要追求速度该怎么做?

与C/C++这类完全编译语言不同的是,python工作中通常没有构建或“make”的步骤: 代码写好后立即运行,另外一个就是 python 字节码不是机器的二进制代码,字节码是特定于 python 的一种表现形式。
这就是python代码无法像C/C++一样快的原因。 PVM循环仍然需要解释字节码。
大多数使用的python都是Cython,是标准的实现,Cython具有调用C函数以及使用变量、参数和类属性的C类型声明的能力。追求速度可以使用C与python混合编程。
(Shed Skin是python 到 C++ 的转换器。尝试将python代码翻译成C++代码,然后使用机器中的C++编译器将得到的C++代码编译为机器代码)

8.数组和元组之间的区别是什么?

数组和元组之间的区别:数组内容是可以被修改的,而元组内容是只读的。另外,元组可以被哈希,比如作为字典的关键字。

9.谈谈你对python中变量、对象和引用的理解

Python中的一切都是类,类型属于对象而不是变量,变量名没有类型,所谓赋值只是让不同的变量名引用不同类型的对象。
变量永远不会拥有和它关联的类型信息或约束。类型的概念存在于对象而不是变量中。变量原本是通用的,他只是在一个特定的时间点,简单地引用了一个特定的对象而已。
当变量出现在表达式中时,它会马上被当前引用的对象所替换,无论这个对象是什么类型。此外,所有的变量必须在使用前明确地被赋值,使用未赋值的变量会产生错误。
简而言之,变量在赋值的时候才会被创建,它可以引用任何类型的对象,而且必须在引用之前赋值。
语句 a=3,变量a实际是到对象内存空间(通过运行常量表达式3而创建)的一个指针。

10.python中的冻结二进制文件你了解多少?

可以通过第三方工具将python程序转为可执行程序,他们在python世界中被称为冻结二进制文件(frozen binary)。这些程序可以不安装python环境而独立运行。冻结二进制文件,能够将程序的字节码,PVM,以及任何程序所需要的python支持文件捆绑在一起形成一个单独的文件包。这个过程存在一些不同的变体,但最终的结果都会产生一个独立的可执行二进制程序,类似Windows系统中的.exe文件。

11.Python都有哪些自带的数据类型?

以python3.5为例,Python自带的数据类型分为可变的和不可变的。可变的有:列表、集合(可变集合)、字典、bytearray(字节数组);不可变的有:字符串、元组、数字、frozenset(不可变集合)。

在Python中,所有的名字都存在于一个空间中,它们在该空间中存在和被操作————这就是命名空间。
它就好像一个盒子,每一个变量名字都对应着一个对象。当查询变量的时候,会从该盒子里面寻找相应的对象。 命名空间是一个字典的实现,键为变量名,值是变量对应的值。各个命名空间是独立没有关系的,一个命名空间中不能有重名,但是不同的命名空间可以重名而没有任何影响。

python程序执行期间会有2个或3个活动的命名空间(函数调用时有3个,函数调用结束后2个)。按照变量定义的位置,可以划分为以下3类:

Local 局部命名空间,每个函数所拥有的命名空间,记录了函数中定义的所有变量,包括函数的入参、内部定义的局部变量。

Global 全局命名空间,每个模块加载执行时创建的,记录了模块中定义的变量,包括模块中定义的函数、类、其他导入的模块、模块级的变量与常量。

Built-in python自带的内建命名空间,任何模块均可以访问,放着内置的函数和异常。

Pass是一个在Python中不会被执行的语句。在复杂语句中,如果一个地方需要暂时被留白,它常常被用于占位符。

Slicing是一种在有序的对象类型中(数组,元组,字符串)节选某一段的语法。

Python中文档字符串被称为docstring,它在Python中的作用是为函数、模块和类注释生成文档。

16.如何在Python中拷贝一个对象?这些拷贝之间有什么区别?

赋值(=),就是创建了对象的一个新的引用,不会开辟新的内存空间。
浅拷贝:创建一个新的对象,其内容是原对象的引用。 浅拷贝有三种形式:切片操作,工厂函数,copy模块中的copy函数。 如: lst = [1,2,3,[4,5]]
copy函数:lst1 = copy.copy(lst) 浅拷贝之所以称为浅拷贝,因为它仅仅只拷贝了一层,在lst中有一个嵌套的list[4,5],如果我们修改了它,情况就不一样了。
深拷贝:创建一个新的对象,并且递归的复制多层嵌套里的对象,深拷贝出来的对象是一个全新的对象,不再与原来的对象有任何关联。(copy模块的deep.deepcopy()函数)

b = a # 指针 b 与 a 指向同一片内存地址:常量 3 所在的内存地址
a = 7 # 指针 a 现在改变指向,指向 7 所在的内存地址

copy浅拷贝(copy.copy()),没有拷贝子对象,所以原始数据改变,子对象会改变;
深copy(copy.deepcopy()),递归的复制它所包含的对象,所以原始对象的改变不会造成深拷贝里任何子元素的改变;
它们的相同之处是,父对象都没有改变.
Python里面如何拷贝一个对象·时间带着假象流淌
Python中的赋值(复制)、浅拷贝、深拷贝之间的区别·碧水幽幽泉

Python中的序列索引可以是正也可以是负。如果是正索引,0是序列中的第一个索引,1是第二个索引。
如果是负索引,(-1)是最后一个索引而(-2)是倒数第二个索引。

18.如何将一个数字转换成一个字符串?

你可以使用自带函数str()将一个数字转换为字符串。如果你想要八进制或者十六进制数,可以用oct()或hex()。

19.Python中的模块和包是什么?

在Python中,模块是搭建程序的一种方式。每一个Python代码文件都是一个模块,并可以引用其他的模块,比如对象和属性。
一个包含许多Python代码的文件夹是一个包。一个包可以包含模块和子文件夹。

20.函数中*args,**kwargs这两个参数是什么意思?我们为什么要使用它们?

如果不确定往一个函数中传入多少参数,或者我们希望以元组(tuple)或者列表(list)的形式传参数的时候,我们可以使用*args(单星号)。如果我们不知道往函数中传递多少个关键词参数或者想传入字典的值作为关键词参数的时候我们可以使用**kwargs(双星号),args、kwargs两个标识符是约定俗成的用法。

另一种答法:当函数的参数前面有一个星号号的时候表示这是一个可变的位置参数,两个星号**表示这个是一个可变的关键词参数。星号把序列或者集合解包(unpack)成位置参数,两个星号**把字典解包成关键词参数。

装饰器本质上是一个Python函数,它可以让其它函数在不作任何变动的情况下增加额外功能,装饰器的返回值也是一个函数对象。它经常用于有切面需求的场景。比如:插入日志、性能测试、事务处理、缓存、权限校验等。有了装饰器我们就可以抽离出大量的与函数功能无关的雷同代码进行重用。
BAT面试题39:Python中的装饰器用过吗?

Python中的垃圾回收是以引用计数为主,标记-清除和分代收集为辅。

引用计数:Python在内存中存储每个对象的引用计数,如果计数变成0,该对象就会消失,分配给该对象的内存就会释放出来。
标记-清除:一些容器对象,比如list、dict、tuple,instance等可能会出现引用循环,对于这些循环,垃圾回收器会定时回收这些循环(对象之间通过引用(指针)连在一起,构成一个有向图,对象构成这个有向图的节点,而引用关系构成这个有向图的边)。
分代收集:Python把内存根据对象存活时间划分为三代,对象创建之后,垃圾回收器会分配它们所属的代。每个对象都会被分配一个代,而被分配更年轻的代是被优先处理的,因此越晚创建的对象越容易被回收。
Python垃圾回收机制--完美讲解!

23.说明os,sys模块不同,并列举常用的模块方法?

os模块是Python标准库中的一个用于访问操作系统功能的模块,使用os模块中提供的接口,可以实现跨平台访问
sys模块负责程序与Python解释器的交互,提供对python解释器相关的操作。
os和sys模块一些常用的方法:

24.什么是lambda表达式?它有什么好处?

lambda 是为编写简单函数而设计的,而 def 能处理更大的任务。lambda 主体结构中只能封装有限的逻辑,连 if 这样的语句都不能使用[P565]。
lambda表达式一般的形式是:关键词lambda后面紧接一个或多个参数,紧接一个冒号“:”,紧接一个表达式。lambda表达式是一个表达式不是一个语句。

25.表达式与语句有什么区别?

Python代码由表达式和语句组成,并由Python解释器负责执行。
它们的主要区别是“表达式”是一个值,它的结果一定是一个Python对象。当Python解释器计算它时结果可以是任何对象。例如42,1+2,int(‘123’),range(10)等。
结果不是对象的代码则成为‘语句’。它们表示的是一个动作而不是生成或者返回一个值。常见的Python语句有print,if/else,def等

__init__为初始化方法,创建对象后,就立刻被默认调用了,可接收参数。
__new__方法是真正的构造函数。__new__是实例创建之前被调用,它的任务是创建并返回该实例。
__init__有一个参数self,就是__new__返回的实例,__init__在__new__的基础上可以完成一些其它初始化的动作,__init__不需要返回值,__init__是实例创建之后被调用的,然后设置对象属性的初始值。
总结:__new__方法在__init__方法之前被调用,并且__new__方法的返回值将传递给__init__方法作为第一个参数,最后__init__给这个实例设置一些参数。

27.Python中单下划线和双下划线分别是什么?

name:一种约定,Python内部的名字,用来与用户自定义的名字区分开,防止冲突

_name:一种约定,用来指定变量私有

__name:解释器用_classname__name来代替这个名字用以区别和其他类相同的命名

自省就是面向对象的语言所写的程序在运行时,所能知道对象的类型。简单一句话就是运行时能够获得对象的类型。比如:type()、dir()、getattr()、hasattr()、isinstance()
Python自省(反射)指南

29.如何在一个函数内部修改全局变量

31.如何删除字典的键以及如何合并两个字典

33.简述with方法打开处理文件帮我我们做了什么?

35.python中生成随机整数、随机小数、0-1之间小数方法

assert()方法,断言成功,则程序继续执行,断言失败,则程序报错。

38.列出python中可变数据类型和不可变数据类型,并简述原理

不可变数据类型:字符串、元组、数值、frozenset。
不可变变量的值发生变化,如果改变了变量的值,相当于新建了一个对象,而对于相同的值的对象,在内存中则只有一个对象(一个地址),如下面代码中用id()方法可以打印对象的id

可变数据类型:列表、集合、字典、bytearray。
可变变量的值发生变化,即如果对变量进行append、+=等这种操作后,只是改变了变量的值,而不会新建一个对象,变量引用的对象的地址也不会变化。对于相同的值的不同对象,在内存中地址不同,即每个对象都有自己的地址,相当于内存中对于同值的对象保存了多份,这里不存在引用计数,是实实在在的对象。

39.字典根据键从小到大排序

41.正则表达式匹配中,(.)和(.?)匹配区别?

(.)是贪婪匹配,会把满足正则的尽可能多的往后匹配
(.
?)是非贪婪匹配,会把满足正则的尽可能少匹配

zip()函数在运算时,会以一个或多个序列(可迭代对象)做为参数,返回一个元组的列表。同时将这些序列中并排的元素配对。
zip()参数可以接受任何类型的序列,同时也可以有两个以上的参数;当传入参数的长度不同时,zip能自动以最短序列长度为准进行截取,获得元组。

1、使用生成器,因为可以节约大量内存
2、循环代码优化,避免过多重复代码的执行
4、多进程、多线程、协程
5、多个if elif条件判断,可以把最有可能先发生的条件放到前面写,这样可以减少程序判断的次数,提高效率
列表推导比手动 for 循环语句运行得更快(往往速度快一倍),这是因为它们的迭代在解释器内部以 C 语言速度执行的,而不是手动以 Python 代码执行的。尤其对于较大的数据集合,使用列表推导能带来极大的性能优势。[P426]

46.简述多线程、多进程

1、操作系统进行资源分配和调度的基本单位,多个进程之间相互独立
2、稳定性好,如果一个进程崩溃,不影响其他进程,但是进程消耗资源大,开启的进程数量有限制 线程:
1、CPU进行资源分配和调度的基本单位,线程是进程的一部分,是比进程更小的能独立运行的基本单位,一个进程下的多个线程可以共享该进程的所有资源
2、如果IO操作密集,则可以多线程运行效率高,缺点是如果一个线程崩溃,都会造成进程的崩溃 应用: IO密集的用多线程,在用户输入,sleep 时候,可以切换到其他线程执行,减少等待的时间 CPU密集的用多进程,因为假如IO操作少,用多线程的话,因为线程共享一个全局解释器锁,当前运行的线程会霸占GIL,其他线程没有GIL,就不能充分利用多核CPU的优势

any():只要迭代器中有一个元素为真就为真
all():迭代器中所有的判断项返回都是真,结果才为真

ImportError:无法引入模块或包,基本是路径问题
IndexError:下标索引超出序列边界
KeyError:试图访问你字典里不存在的键
NameError:使用一个还未赋予对象的变量

若 L 为列表,L.sort() 无返回值,就地更改列表
sorted(L) 返回一个新的排好序的列表,原列表无变化

首先,要知道sorted 内部实现使用了归并排序,而归并排序是稳定的排序,就是说当元素比不出大小时,其相对位置是不变的。
那么,利用稳定排序的特性,key函数有几个返回值就排序几次,先排序次要条件,后排序主要条件(条件从前到后重要程度依次降低),用主要条件覆盖次要条件,主要条件相同时,又不会改变之前排好的次要条件的相对位置,就实现了多条件排序。
给我们的直观效果是,主要条件排不出先后顺序的元素,就按照次要条件排序。

52.用两种方法去空格

python垃圾回收主要以引用计数为主,标记-清除和分代清除为辅的机制,其中标记-清除和分代回收主要是为了处理循环引用的难题。
当有1个变量保存了对象的引用时,此对象的引用计数就会加1,当使用del删除变量指向的对象时,如果对象的引用计数不为1,比如3,那么此时只会让这个引用计数减1,即变为2,当再次调用del时,变为1,如果再调用1次del,此时会真的把对象进行删除。

54.Python传参数是传值还是传址?

python中函数参数是引用传递(注意不是值传递)。
对于不可变类型(数值型、字符串、元组),因变量不能修改,所以运算不会影响到变量自身;
而对于可变类型(列表字典)来说,函数体运算可能会更改传入的参数变量。

Lock(GIL)的东西,它能确保你的代码中永远只有一个线程在执行。经过GIL的处理,会增加执行的开销。这就意味着如果你先要提高代码执行效率,使用threading不是一个明智的选择,当然如果你的代码是IO密集型,多线程可以明显提高效率,相反如果你的代码是CPU密集型的这种情况下多线程大部分是鸡肋。

在Python中一切都是对象。Python中对象包含的三个基本要素,分别是:id(身份标识)、type(数据类型)和value(值)。对象之间比较是否相等可以用==,也可以用is。
is 和 == 都是对对象进行比较判断作用的,但对对象比较判断的内容并不相同。

59.集合有哪些运算?

集合的运算与数学上的集合类似

60.列出字符串常用操作

s.lower() 将字符串转换为小写,大小写仅限于英文字符
s.islower() 判断字符串是否为小写,输出为布尔类型
s.isupper() 判断字符串是否为大写,输出为布尔类型
s.isalpha() 判断字符串是否由字母组成,输出为布尔类型
s.isdigit() 判断字符串是否由数字组成,输出为布尔类型
s.isalnum() 判断字符串是由字母或数字字符组成,输出为布尔类型
s.strip() 删除字符串首尾的空白字符
s.lstrip() 删除字符串首部的空白字符,这里的'l'是英文单词left
s.rstrip() 删除字符串尾部的空白字符,这里的'r'是英文单词right
s.find() 从左到右查找某字符串第一次出现的位置,如果查不到,则返回值为-1
s.rfind() 从右到左查找某字符串第一次出现的位置,如果查不到,则返回值为-1
s.count() 统计字符串出现的次数, 若没有相应的字符串,则返回0
s.startswith()、s.endswith() 分别用来判断字符串是否以指定的子字符串开始或结束,返回值为布尔类型。

61.列出列表的常用操作

L.extend(iter) 在列表尾部添加另一个可迭代对象 extend方法传入的是一个可迭代的对象,在使用extend方法时会将可迭代对象中的元素逐个加入到列表中。

62.两个等长列表如何构造字典?

64.迭代器和可迭代对象分别是什么,它们之间有什么区别?

如果一个对象定义了 iternext 两个方法,它就是一个迭代器。对于迭代器来说,iter 返回的是它自身 self,next 则是返回迭代器中的下一个值,如果没有值了则抛出一个 StopIteration 的异常。(关于这点,你可以想象成一个只进不退的标记位,每次调用 next,就会将标记往后移一个元素并返回,直到结束。)
如果一个对象定义了 iter 方法,返回一个迭代器对象,那么它就是一个可迭代的对象。 如果一个对象可迭代,那么就可以被 for 循环使用。比如经常用到的 list、dict、str 等类型。 迭代器(Iterator)和可迭代(Iterable)区别:
一个迭代器一定是可迭代对象,因为它一定有 iter 方法。反过来则不成立。(事实上,Iterator 就是 Iterable 的子类)
迭代器的 iter 方法返回的是自身,并不产生新实例。而可迭代对象的 iter 方法通常会生成一个新的迭代器对象。iternext 分别对应于 Python 的内置函数 iter() 和 next()。

65.单遍迭代器与多遍迭代器有什么区别?

与 range 类似,内置函数 map、zip 和 filter 在 Python3.X 中也可以转换成可迭代对象以节约内存空间,而不是一次性在内存中产生一个结果列表。与 range 不同,map、zip 和 filter它们本身都是迭代器——在遍历一次后,它们就用尽了(单遍迭代器)。换句话说,你不能在它们的结果上拥有多个位于不同位置的迭代器(多遍迭代器)。

times 函数中表达式 x * y 的意义完全取决于 x 和 y 的对象类型,同样的函数,在一种对象下执行的是乘法(3 * 3),在另一种对象下执行的确是重复(‘a’ * 3)Python 把对某一对象在某种语法下的合理性交给那个对象自身来判断,* 作为一个分派机制,将执行的控制权移交给被处理的对象。这种依赖类型的行为称为多态。其含义就是一个操作的意义取决于被操作对象的类型。

工厂函数(闭包)能够记忆外层作用域里的值,不管那些嵌套作用是否还在内存中存在。

内嵌函数记住了 N = 2,即maker内部的变量N。实际上,在外层嵌套局部作用域内的N被作为执行状态信息保留了下来,并附加到生成的 action 函数上。
如果再调用外部函数,可以得到一个新的不同状态信息的嵌套函数。

每次对工厂函数的调用,都将得到属于调用自己的状态信息的集合。我们使 g 函数记住了 N = 3,使 f 函数记住了 N = 2。每个函数都有自己的状态值,这个状态信息由 maker 中的变量 N 决定。

68.谈谈类中的访问限制

如果要让内部属性不被外部访问,可以把属性的名称前加上两个下划线__,在Python中,实例的变量名如果以__开头,就变成了一个私有变量(private),只有内部可以访问,外部不能访问,内部访问用 self.__x。

需要注意的是,在Python中,变量名类似__xxx__的,也就是以双下划线开头,并且以双下划线结尾的,是特殊变量,特殊变量是可以直接访问的,不是private变量。
以一个下划线开头的实例变量名,比如_name,这样的实例变量外部是可以访问的,但是,按照约定俗成的规定,当你看到这样的变量时,意思就是,“虽然我可以被访问,但是,请把我视为私有变量,不要随意访问”。 双下划线开头的实例变量是不是一定不能从外部访问呢?其实也不是。

在索引优化时,经常会看到的一句话:如果索引字段出现隐式字符集转换的话,那么索引将失效,进而转为全表扫描,查询效率将大大降低,要避免出现隐式字符集转换;

  • 大家知道为什么隐式字符集转换会导致索引失效吗?

  • 实际场景中有没有遇到过隐式字符集转换导致索引失效的场景,具体排查的过程;

由上面的两个问题牵引出了本文的主线;

  • 简单描述下隐式字符集转换导致索引失效的原因

  • 然后模拟实际场景排查隐式字符集转换导致索引失效的过程

隐式字符集转换导致索引失效的原因

MySQL索引的数据结构是 B+Tree,想要走索引查询必须要满足其 最左前缀原则 ,否则无法通过索引树进行查找,只能进行全表扫描;

例如:下面的这个SQL由于在 索引字段 上使用函数进行运算,导致索引失效

上面的这个SQL怎么改造才能使索引生效呢?如下所示:

通过上面的小例子可以知道,如果在索引字段上使用函数运算,则会导致索引失效,而索引字段的 隐式字符集转换 由于MySQL会自动的在索引字段上加上 转换函数 ,进而会导致索引失效;

那接下来我们就通过模拟的实际场景来具体看看是不是由于MySQL自动给加上了转换函数而导致索引失效的;

模拟场景 + 问题排查

由于导致索引失效的原因有很多,如果自己写的SQL怎么看都没问题,但是通过查看执行计划发现就是没有走索引查询,此时就会让很多人陷入困境,这到底是怎么导致的呢?

使用这个工具可以将执行的SQL语句的一些扩展信息展示出来,这些扩展信息就包括:MySQL优化时可能会添加上字符集转换函数,使得字符集不匹配的SQL可以正确执行下去;

模拟隐式字符集转换的场景:

首先创建两个字符集不一样的表:

然后使用存储过程构造数据:


注意:在构造数据时,记得将 t_employees 表中的 de_no 字段值构造的 离散些 ,因为如果索引字段值的 区分度很低 的话,那么MyQSL优化器通过采样统计分析时,发现索引查询和全表扫描性能差不多,就会直接进行全表扫描了;

索引失效的查询SQL语句:

将表和数据构造完后,我们使用SQL语句进行查询下,然后再看看其执行计划;

发现 t_employees 表中的 de_no 字段有索引,但是没有走索引查询,type=ALL 走的全表扫描,但是通过查看SQL语句发现其没有问题呀,表面看上去都是满足走索引查询的条件呀,排查到这发现遇到了困境,苦恼啊!

还好,通过在网络世界上遨游,最终发现了 explain extended + show warnings 利器,利用它快速发现了索引失效的根本原因,然后快速找到了解决方案;

下面就来聊聊这个利器的具体使用,开森!

使用利器快速排查问题:

注意:explain 后面跟的关键字 EXTENDED(扩展信息) 在MySQL5.7及之后的版本中废弃了,但是该语法仍被识别为向后兼容,所以在5.7版本及后续版本中,可以不用在 explain 后面添加 EXTENDED 了;

EXTENDED关键字的具体查阅资料:

①、首先在MySQL的可视化工具中打开一个 命令列介面 :工具 --> 命令列介面

②、然后输入下面的SQL并按回车:

③、然后紧接着输入命令 show warnings; 并回车,会出现如下图所示内容:

通过展示出的执行SQL扩展信息,发现MySQL在字符集不一致时自动添加上字符集转换函数,因为是在 索引字段 de_no 上添加的转换函数,所以就导致了索引失效;

而如果我们没看扩展信息的话,那么可能直到我们查看表结构的时候才会发现是由于字符集不一致导致的,这样就会花费很多的时间;

咱们聊完上面的隐式字符集转换导致索引失效的情况,再来简单聊聊另一种 隐式类型转换 导致索引失效的情况;

隐式类型转换:简单的说就是字段的类型与其赋值的类型不一致时会进行隐式的转换;

至此本文进入结尾,在此再说明下,上文中测试时使用的MySQL版本都是 5.7

如果本文对您有帮助的话,请挥动下您爱发财的小手点下赞呀,您的支持就是我不断创作的动力,谢谢啦!

您可以微信搜索 【木子雷】 公众号,大量Java学习干货文章,您可以来瞧一瞧哟!

基础不牢固,特别不牢固,项目无从下手!

这次花一个星期的时间把Python的基础库学习一下,一来总结过去的学习,二来为深度学习打基础。

部分太简单,或者映象很深的就不记录了,避免浪费时间。

time模块顾名思义与时间相关,我们平时主要使用日期计时

学习机器学习的时候看到的一个小模块,当然实现的方法很多。
给定一个一个样本集[[1,2,3],[4,5,6],[7,8,9]....],假设含有100个样本,现在要对样本进行训练,每个样本训练一次,且每个样本都是随机的,怎么取合适?

padndas表格处理模块,相对于numpy是对统一的数据进行操作,pandas是对表格(不通的数据类型)进行的操作

pandas的基本构成是数据帧,其中索引是X轴,数据是Y轴.

pandas中使用Nan代表缺失的数据

  • Splitting :基于一些标准把数据分成组
  • Applying:分别对每个组应用操作函数
  • Combining:将结果构建成一个数据结构





我要回帖

更多关于 oracle 基于函数的索引 的文章

 

随机推荐