• django优化和扩展(一)


    mysql优化基础

        进行django产品开发或上线之前,有必要了解一下mysql的基础知识,orm太过抽象,导致很多朋友对于mysql了解得太少,而且orm不像sqlalchemy那样可以跟mysql走的那么近!如果要设计出合理的表结构(在orm中就是model类),显然把一个ip设置成64个字符是大大地浪费。本文结合mysql手册,做一些建表优化。

    一、尽可能地使用最有效(最小)的数据类型

    class Customer(models.Model):
        qq = models.CharField(u"QQ号",max_length=64,unique=True)
        name = models.CharField(u"姓名",max_length=32,blank=True,null=True)
        phone = models.BigIntegerField(u'手机号',blank=True,null=True)
        stu_id = models.CharField(u"学号",blank=True,null=True,max_length=64)

    上面这个类从优化角度显然是不合理的,一个qq号占64个字符,姓名32个字符,手机号用的bigint,学号64位,一行数据得占多大空间,下面两张图写明了主要数据类型的区别!

    (一)、整形列的应用

    整形列的选择要慎重,一定要坚持最小化的原则,而且一定要选择无符号的整数,在orm无符号的声明如下:

    class cj_user(models.Model):
        cjid = models.PositiveIntegerField() # Positive 开头一般都是无符号


    # 在声明非主键字段时可以如上应用,如果优化主键,必须重写AutoField,因为orm默认生成的是int类型,且是有符号的,优化方法可以参照我最后写的

    (二)、char、varchar、text的区别

    讲之前问2个问题:

    1,char(5)和varchar(5) 能不能存下'abcdefg'?

    2,char(5)和varchar(20)同样存'abcd'各占几个字符?几个字节?

    ()中的数字都是字符数,如果要算字节数必须utf-8*3 gbk*2,但varchar是变长,内容多少就占多少,他有一点比较特殊,varchar(20)存'abc'的时候占4个字符,因为在末尾加

    在工作中应尽量使用定长,如char和上面的整形列 都是定长,有利加速,变长通常用一对一的形式存在附加表中,也可以综合应用,但最佳的优化还是分表存储!手机,身份证、姓名、密码都是比较固定的字段,如密码,无论设几位,最后都会被加密成32位字符串!以下是我的用户表( FixCharField是我自定义的char,因为在orm中不支持char,CharField生成的是varchar变长类型。在本文的最后我会讲一下,如何自定义!)

    class hwj_user(models.Model):
        xm = FixCharField(max_length=4)
        tel = FixCharField(max_length=11)
        sfz = FixCharField(max_length=18)
        pwd = FixCharField(max_length=32)

    注:varchar(max)的单位是字节即最多存65535个字节,以utf-8为例,约2万多个汉字!

    (三)主键和非空字段要用not null

    手册上说:如果可能,声明列为NOT NULL。它使任何事情更快而且每列可以节省一位。这点orm中已经默认这么干了,当然这里也建议你不要把

    null=True写上去

    二、慎用索引

    索引是会加快速度,但我觉除了主键、多对多的表无法避免外,其他都要慎用,因为索引会加快查询速度,却会降低写入速度,如果你的表有类似频繁写入的功能,如抢购等,那你就不要使用,像唯一这种都属于索引,尽量在业务中去判断他是否存在。

    三、多设默认值

    默认值的设置也是优化的一方面,也能使数据层避免产生错误,即便是not null的列,也应该给他设上default='',数值类型default=0等等!

    四、随机排序的实现

    由于orm不支持随机排序,如果要实现数据的随机排机,只能借助于python(也可以重写oder_by但太复杂了)

       ids = models.Tk.objects.filter(eid_id=exam_data.id).all().values('id')
        rand_id=[]
        for id in ids:
            rand_id.append(id["id"])
        rand_num = random.sample(rand_id,5)
        print(rand_num)
        tks = models.Tk.objects.filter(eid_id=exam_data.id,id__in=rand_num).all()

    1,先取出所有的id,把他们放到列表

    2,利用random.sample 在列中随机选择5个id

    3,利用orm的id__in过滤出id所在行的记录

    五、自定义数据类型

    class FixCharField(models.Field):
        def __init__(self, *args, **kwargs):
            super(FixCharField, self).__init__(*args, **kwargs)
    
        def db_type(self, connection):
            return 'char(%s)' % self.max_length
    
    
    class hwj(models.Model):
        my_field = FixCharField(max_length=25)

    只是重写了,具体可看django源码

    六、模板中的计数 上层循环计数

    有的时候要输出上层循环的计数值,在相关书籍上也只看到当前循环{{ forloop.counter }},看了底层才知道还有forloop.parentloop.counter

    以向是我模板中用反向查找实现了在题目下显示题目的方法,用嵌套循环实现的!

        {% for o in tks %}
        <div class="panel panel-info">
      <!-- Default panel contents -->
      <div class="panel-heading" name="ks{{ o.attr }}">{{ forloop.counter }}、{{ o.subject }}</div>
      <div class="panel-body">
    
         {% for i in o.op_set.all %}
    
      <p><input type="radio" name="dx{{ forloop.parentloop.counter }}" title="{{o.answer}}"  class="option-input radio" value="{{i.opstr}}"> {{i.opstr}} {{i.opname}}</p>
      <p style="padding:0; margin:0; height:5px;"></p>
    {% endfor %}

    马上开会了,今天就写到这里。

  • 相关阅读:
    mysql函数
    存储过程1
    linux下手动安装git教程
    python离线安装外部依赖包
    自动代码质量分析(GitLab+JenKins+SonarQube)
    Jenkins定时构建和轮询SCM设置说明
    jenkins
    linux在当前目录下根据文件名查找文件
    elastic search报错——“failed to obtain node locks”
    linux下rpm包安装、配置和卸载mysql
  • 原文地址:https://www.cnblogs.com/sunface/p/5553086.html
Copyright © 2020-2023  润新知