【问题标题】:better solution for selecting updating many values选择更新许多值的更好解决方案
【发布时间】:2012-07-09 04:49:05
【问题描述】:

我想根据不同的情况更新列中的一些值..... 该表具有以下详细信息,例如.....

                    Date               date
                    period             int
                    subcode            varchar(3)
                    status_bits        varchar(100)
                    // status bits resemble an information based code based...the data usually stored are  2343211 where each value in digits represent an information.....

现在我必须根据不同的日期和时期更新这些值.... 现在考虑java program......

我已将详细信息存储在 java 中的相应变量中,例如..

                   java.util.Date date[];
                   int period[];
                   String subcode[];

                   // Here for an index i , they share the same values within a row.....

如果我想以这样一种方式更新它,即我想将 varchar 中的第 5 个字母更改为不同的日期、期间和子代码(组合)..... 现在..我目前的表现是这样的......

     Connection con;
     preparedStatement ps;
     String bitstatus;



     for(i=0; i < noofupdates; i++)
     {
           ps = con.prepareStatement("select status_bits from tablename where Date = ? AND period = ? AND subcode = ? limit 0,1");
           ps.setDate(1,date[i]);
           ps.setInt(2,period[i])'
           ps.setString(3,subcode[i]);

           rs=ps.executeQuery();
           while(rs.next())
           {

                 bitstatus = rs.getString(1);
                 // performed operation to update the bit.....
                 ps=con.prepareStatment("update status_bits correspondind to the same date,field and subcode");

                 ps.executeUpdate();
           }

     }

现在我假设您从程序中了解到我想根据位操作常见的不同日期和期间更新表中的 status_bits......现在我真的知道了这些方法正在敲击大量查询并严重影响 mysql 性能......所以请通过提供一个替代想法来帮助我......有大约 1000 条记录要更新......

【问题讨论】:

    标签: java mysql database-design


    【解决方案1】:

    如果您知道要将 status_bits 字符串的第 5 位设置为给定(日期、期间、子代码)的特定值,则可以避免 SELECT 并仅执行更新。

    更新: 为了正确处理 status_bits 列中的现有值小于 4 个字符的情况,我们要确保在现有字符串为只有 1 个字符长。我们可以使用 CASE 表达式来进行测试。当我们至少有 4 个字符时,我们可以在前四个字符之后附加我们的(所需的)第 5 个字符。否则,我们需要将现有字符串“填充”为 4 个字符,然后再添加(所需的)第 5 个字符。 (以前,该语句仅包含适用于长度至少为 4 个字符的现有字符串的表达式。)

    UPDATE tablename
       SET status_bits = 
           CASE WHEN CHAR_LENGTH(status_bits >= 4
             THEN CONCAT(LEFT(status_bits,4), ?, SUBSTR(status_bits,6))
             ELSE CONCAT(RPAD(status_bits,4), ? )
             END
     WHERE `Date` = ? AND period = ? AND subcode = ? 
    

    (如果您不想更新所有匹配的行,您可以添加 LIMIT 子句,但如果您想更新所有匹配的行,则不需要。如果(date,period,subcode) 是唯一的,您将最多匹配一个行。)

    还可以根据其他条件设置 status_bits 的第 5 位,例如,通过在 where 子句中添加谓词,或在 SET 中添加 CASE 表达式(或 IF 函数)。

    UPDATE tablename
       SET status_bits = CONCAT(LEFT(status_bits,4)
                         , IF(SUBSTR(status_bits,1,1 = '1', ?, SUBSTR(status_bits,5,1))
                         , SUBSTR(status_bits,6))
     WHERE `Date` = ? AND period = ? AND subcode = ? 
    

    相当于:

    UPDATE tablename
       SET status_bits = CONCAT(LEFT(status_bits,4), ?, SUBSTR(status_bits,6))
     WHERE `Date` = ? AND period = ? AND subcode = ? 
       AND SUBSTR(status_bits,1,1) = '1'
    

    这种方法将您正在运行的查询数量减少一半(减少到数据库的往返次数)并避免您必须返回整个 status_bits 列。

    (不幸的是,替换 varchar 列的第 5 个字符的 SQL 文本有点笨拙,因为 MySQL 没有 SQL Server 提供的更紧凑的 STUFF 函数。)


    更新: 处理长度小于 4 个字符的现有 status_bits 字符串需要更复杂的表达式...)

    UPDATE tablename
       SET status_bits = 
           CASE WHEN CHAR_LENGTH(status_bits) >= 4
                THEN CONCAT(LEFT(status_bits,4), ? , SUBSTR(status_bits,6))
                ELSE CONCAT(RPAD(status_bits,4,' '), ? )
           END
     WHERE `Date` = ? AND period = ? AND subcode = ?
    

    注意:在该 SQL 语句中,要放置在第 5 位的字符的值需要在两个单独的位置参数中提供。

    注意:

    【讨论】:

    • cool....但是你认为...它会影响性能...因为...就像我们应用字符串函数...rite..??
    • 不,对性能影响不大。您最大的性能问题将是在(date,period,subcode)(或其他一些合适的索引)上有一个可用的索引。工作量实际上大致相同,定位行并替换 status_bits 列。实际上,在数据库端这样做会更快,而不是返回整个 status_bits 字符串并将其发送回去。
    • 您的意思是日期、期间和子代码只有一个主键....???...是这样..??
    • 这不一定是你的主键。为了提高性能,您只需要一个索引,其中至少有一些列作为前导索引,最好是最有选择性的列。如果此列组合是 UNIQUE,您可以创建一个 UNIQUE KEY。
    • 好吧..我已经将这 3 列设为复合主键,并且子代码引用了不同的主键......这是否足够好......或者是你的其他东西正在建议.....
    【解决方案2】:

    您首先从数据库中读取一些数据(status_bits),然后根据检索到的记录数多次调用多个数据库。

    相反,你为什么不写一个存储过程,它将日期、期间和子代码作为参数,并在 SP 本身中执行整个逻辑?

    这样你只有 1 个 DB 调用。

    【讨论】:

    • 实际上......我选择了对应于日期、期间和子代码(它们是复合的)的状态位......如果我得到一个值......我正在执行位操作和更新它到包含该日期、期间和子代码的同一行.....If u really think that this can be performed with one query ..!!Cud 你请提供一个例子....因为这就是我想要的..
    • 你在执行什么位操作?我在你的代码中没有看到它?
    • it just replacing a char in a string...我没有包括因为它是编程部分......现在真正的问题是现在发出大量查询......i really would like to know how this can be accompllishes using minimum no of queries......! !
    • 不确定是什么问题。 REPLACE 是一个 SQL 函数,可用于在 SQL 代码中替换字符串中的字符。见1keydata.com/sql/sql-replace.html
    猜你喜欢
    • 1970-01-01
    • 2013-07-21
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2014-02-03
    • 2014-07-20
    • 2011-11-21
    相关资源
    最近更新 更多