【问题标题】:Mysql server side paging , sortingMysql服务器端分页、排序
【发布时间】:2018-11-07 18:34:38
【问题描述】:

您好,我在数据库中有一张表,其中包含多列,超过 20 列,它包含许多大约 200 万条记录

该表有一个主键:Col1,它也是我的表的索引 , 由于某些原因,该列的数据类型是 varchar(200)。

我正在实现服务器端分页、排序和稍后(过滤)

我遇到了性能问题,这是我的程序

DELIMITER $$

CREATE DEFINER=`master`@`%` PROCEDURE `spGetData`(
    IN  DisplayStart int ,
    IN  SortCol int ,
    IN  SortDir nvarchar(10),
    IN  Search  nvarchar(255)
)
BEGIN

        DECLARE FirstRec int;
        DECLARE LastRec int;

        SET FirstRec = DisplayStart;

            select 
               col1,col2,col3,col4,col6,col7,col8,col9,col10,col11
               col12,col13,col14,col15,col16,col17,col18,col19,col20
               col21,
                ( select count(*) from myTable) as filtered

            from myTable



order by
case When (@SortCol = 0 and @SortDir = 'asc')  then col1 end asc ,
case When (@SortCol = 0 and @SortDir = 'desc') then col1 end desc ,

case When (@SortCol = 1 and @SortDir = 'asc')  then col2 end asc ,
case When (@SortCol = 1 and @SortDir = 'desc') then col2 end desc ,

case When (@SortCol = 2 and @SortDir = 'asc')  then col3 end asc ,
case When (@SortCol = 2 and @SortDir = 'desc') then col3 end desc ,

case When (@SortCol = 3 and @SortDir = 'asc')  then col4 end asc ,
case When (@SortCol = 3 and @SortDir = 'desc') then col4 end desc ,

case When (@SortCol = 4 and @SortDir = 'asc')  then col5 end asc ,
case When (@SortCol = 4 and @SortDir = 'desc') then col5 end desc ,

case When (@SortCol = 5 and @SortDir = 'asc')  then col6 end asc ,
case When (@SortCol = 5 and @SortDir = 'desc') then col6 end desc ,

case When (@SortCol = 6 and @SortDir = 'asc')  then col7 end asc ,
case When (@SortCol = 6 and @SortDir = 'desc') then col7 end desc ,

case When (@SortCol = 7 and @SortDir = 'asc')  then col8 end asc ,
case When (@SortCol = 7 and @SortDir = 'desc') then col8 end desc ,

case When (@SortCol = 8 and @SortDir = 'asc')  then col9 end asc ,
case When (@SortCol = 8 and @SortDir = 'desc') then col9 end desc ,

case When (@SortCol = 9 and @SortDir = 'asc')  then col10 end asc ,
case When (@SortCol = 9 and @SortDir = 'desc') then col10 end desc ,

case When (@SortCol = 10 and @SortDir = 'asc')  then col11 end asc ,
case When (@SortCol = 10 and @SortDir = 'desc') then col11 end desc ,

case When (@SortCol = 11 and @SortDir = 'asc')  then col12 end asc ,
case When (@SortCol = 11 and @SortDir = 'desc') then col12 end desc ,

case When (@SortCol = 12 and @SortDir = 'asc')  then col13 end asc ,
case When (@SortCol = 12 and @SortDir = 'desc') then col13 end desc ,

case When (@SortCol = 13 and @SortDir = 'asc')  then col14 end asc ,
case When (@SortCol = 13 and @SortDir = 'desc') then col14 end desc ,

case When (@SortCol = 14 and @SortDir = 'asc')  then col15 end asc ,
case When (@SortCol = 14 and @SortDir = 'desc') then col15 end desc ,

case When (@SortCol = 15 and @SortDir = 'asc')  then col16 end asc ,
case When (@SortCol = 15 and @SortDir = 'desc') then col16 end desc ,

case When (@SortCol = 16 and @SortDir = 'asc')  then col17 end asc ,
case When (@SortCol = 16 and @SortDir = 'desc') then col17 end desc ,

case When (@SortCol = 17 and @SortDir = 'asc')  then col18 end asc ,
case When (@SortCol = 17 and @SortDir = 'desc') then col18 end desc ,

case When (@SortCol = 18 and @SortDir = 'asc')  then col19 end asc ,
case When (@SortCol = 18 and @SortDir = 'desc') then col19 end desc ,

case When (@SortCol = 19 and @SortDir = 'asc')  then col20 end asc ,
case When (@SortCol = 19 and @SortDir = 'desc') then col20 end desc ,

case When (@SortCol = 20 and @SortDir = 'asc')  then col21 end asc ,
case When (@SortCol = 20 and @SortDir = 'desc') then col21 end desc ,


                limit FirstRec,10;

    END

查询速度很慢,并且会出现缓冲区大小问题。 如果我删除 order by 子句,它会变得非常快。

所以我的问题是

1- 我怎样才能增强这个查询并使数百万行的排序变得快速?

2- 稍后我将使用 where 子句对多个列应用过滤,如何避免任何性能问题?

【问题讨论】:

    标签: mysql performance database-performance


    【解决方案1】:
    • 应该构造(concat、prepare、execute、deallocate)ORDER BY,而不是使用不能使用任何索引的巨大表达式。
    • 添加INDEX(col0), INDEX(col1), ... 是可能的,但不现实,这样准备好的语句在所有21 种情况下都会很快。选择重要的,不要将其余的提供给最终用户。
    • Don't use OFFSET to paginate;而是“记住你离开的地方”。
    • 过滤在哪里?这可能会干扰我已经给你的提示。
    • VARCHAR(200) 通常不适合 PRIMARY KEY
    • 用户能否指定对两列进行排序?过滤日期范围?其他事情? (如果您想了解更多详情,请提供真实的SHOW CREATE TABLE。)
    • 您是否对任何列进行了“规范化”?也就是说,将大的、经常重复的值移动到其他表中。

    【讨论】:

    • 嗨@rick,ORDER BY 应该被构造(concat,prepare,execute,deallocate)而不是拥有不能使用任何索引的巨大表达式。你能澄清更多吗?
    • 搜索“mysql procedure concat prepare”,你可能会找到很多例子。
    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2012-09-13
    • 2020-05-09
    • 2013-06-28
    • 2019-04-30
    相关资源
    最近更新 更多