MySql中的查询性能处理大量数据时

时间:2017-05-25 12:15:34

标签: mysql performance query-optimization

我的表包含20000个数据。我必须创建一个新表来计算一些关于分析的记录。在新表中我必须创建25个coloumns。我从中创建了根据我的条件计算所有记录的查询和脚本。但最后三个coloumns需要很多时间。我已经优化了计算其他23种颜色的查询。现在查询最后三个coloumns如下:(1)年度不续约

select  count(*)
    from  payment
    where  (find_in_set('Standard',product)
              OR  find_in_set('Lite',product)
              OR  find_in_set('Basic',product)
              OR  find_in_set('Nifty50',product)
              OR  find_in_set('NiftyOnly',product)
           )
      AND  '" + subscriptionDate + "' NOT BETWEEN subscr_date AND end_date
      AND  payment_type ='annual'
    HAVING  (MIN(subscr_date) < '" + subscriptionDate + "');

(2)季度不续约:

select  count(*)
    from  payment
    where  (find_in_set('Standard',product)
              OR  find_in_set('Lite',product)
              OR  find_in_set('Basic',product)
              OR  find_in_set('Nifty50',product)
              OR  find_in_set('NiftyOnly',product)
           )
      AND  '" + subscriptionDate + "' NOT BETWEEN subscr_date AND end_date
      AND  (payment_type ='quarter'
              OR  payment_type='Quarterly'
           )
    HAVING  (MIN(subscr_date) < '" + subscriptionDate + "');

(3)未续订的月份:

select  count(*)
    from  payment
    where  (find_in_set('Standard',product)
              OR  find_in_set('Lite',product)
              OR  find_in_set('Basic',product)
              OR  find_in_set('Nifty50',product)
              OR  find_in_set('NiftyOnly',product)
           )
      AND  '" + subscriptionDate + "' NOT BETWEEN subscr_date AND end_date
      AND  payment_type ='month'
    HAVING  (MIN(subscr_date) < '" + subscriptionDate + "');

我使用find_in_set()仅检查产品。这3个查询将在while循环下运行,该循环将针对20000个数据进行迭代。现在我该如何减少这些查询的执行时间?

3 个答案:

答案 0 :(得分:1)

您似乎有一个列product,它必须是以逗号分隔的产品名称字符串。

您无法使用索引优化此查询。这是关系数据库中的many reasons why storing comma-separated lists of values is a bad idea之一。

想一下电话簿。如果我要求您查找电话簿中第一个名称为&#39; Karan&#39;的所有条目,那么很难做到。它们可以在书中的任何位置,而不是组合在一起,因为条目的排序顺序不是名字。

当您在逗号分隔的列表中搜索您正在执行的条目时,这是一个类似的问题。您要查找的值可能位于列表的开头,也可能位于结尾或中间。即使列上有索引,它也不能使用索引的排序顺序在逗号分隔列表的中间或末尾查找条目。

如果要搜索列表中的各个元素,则不应使用以逗号分隔的列表。您应该将每行中的元素存储在引用您的付款表的第二个表中。

这是一个非常基本的数据库规范化实践,如果你想进行数据库设计,你应该研究它。这可能就是为什么草莓认为发表他完全无益和不屑一顾的评论是合适的(尽管他/她错了 - 它从来不适合粗鲁)。

答案 1 :(得分:0)

当对行应用简单的布尔条件时,SQL查询运行得更好。 由于您的大部分条件都是find_in_set,因此该查询需要每行执行大量操作。

最佳做法是将数据标准化 - 在您的情况下,您需要将其带到1NF - 这也称为无法翻转或融化。

而不是看起来像这样的行:

KEY SET

1 o1,o2,o3

表格如下所示:

关键选项

1 o1

1 o2

1 o3

答案 2 :(得分:0)

COUNTMINGROUP BY没有SHOW CREATE TABLE就没有意义。在确定(或解释)这个之后,我们可以帮助您。

尝试编写复杂的SQL,而不是遍历行。那将可能加快速度。

让我们看看INDEX(payment_type, subscr_date) 。这些查询需要这个:

WHERE "constant" BETWEEN start AND end

private onInitFormatHandler: Subscription; // <-- ADDED HANDLER AS MEMBER VARIABLE INSTEAD @HostListener('focus', ['$event']) onFocus(event: KeyboardEvent) { // Remove initial formatting subscription since no patch of the value has // occurred, and is no longer likely to occur if the user is actively // applying focus // --- // NOTE: Not unsubscribing causes formatting to occur on dynamically added // fields on the first change of the input value prior to blur if (!this.onInitFormatHandler.closed) { // <-- ADDED CHECK AND EXTRA UNSUBSCRIPTION this.onInitFormatHandler.unsubscribe(); } const float = this.getFloat(); if (float) { this.element.value = this.replace(float); } } public ngOnInit() { this.formatFloat(); } /** * Format the input value only once after the initial form response has * patched the model. * --- * NOTE: Format handler is stored and unsubscribed either on valueChange, or * if focus is applied to the field, whichever occurs first. */ private formatFloat() { this.onInitFormatHandler = this.ngControl.valueChanges // <-- UPDATED HANDLER TO BE MEMBER VARIABLE .subscribe((value: string) => { const float = this.getFloat(); if (float) { this.element.value = this.format(value); } this.onInitFormatHandler.unsubscribe(); // <-- UPDATED HANDLER TO BE MEMBER VARIABLE }); } 很难优化。