MySQL服务器速度变慢,直到选择blob时所有查询都超时

时间:2017-04-25 10:16:06

标签: c# mysql blob innodb

我将个人资料照片存储在我的数据库中,并且我编写了一个小型C#控制台应用程序,它应该只是将这些照片导出到磁盘的某个地方。我一次选择10张照片:

const int pageSize = 10;

using (var connection = new MySqlConnection(_options.Connectionstring))
{
    connection.Open();
    var pageCount = pageSize;

    for (var page = 0; pageCount == pageSize; page++)
    {
        using (var command = new MySqlCommand($"SELECT
              p.FirstName, p.LastName, p.Department, ph.Data
          FROM Persons p
          INNER JOIN Photos ph ON ph.PersonId = p.Id
          LIMIT {pageSize} OFFSET {page * pageSize}", connection)
        using (var reader = command.ExecuteReader())
        {
            for (pageCount = 0; reader.Read(); pageCount++)
            {
                var path = GetFilePath(reader, _options.Pattern);
                EnsureDirectoryExists(path);
                File.WriteAllBytes(path, (byte[])reader["Data"]);
            }
        }
    }
}

稍微修改了代码以使其更简洁,但我主要删除了一些验证和日志记录。

在运行应用程序时监视MySql Workbench中的服务器显示“InnoDB缓冲区使用情况”缓慢上升,直到大约2分钟后达到100%或选择了1000个图像。从我所看到的这是完全正常的,但应用程序也导出图像越来越慢,直到InnoDB缓冲区接近100%,此时应用程序开始超时:

  

超时已过期。操作完成之前经过的超时时间或服务器没有响应。

数据库服务器信息:

  • MySQL服务器5.6
  • 所有表格均使用InnoDB
  • innodb_buffer_pool_size = 1GB
  • 在具有8 GB RAM的Windows Server 2012上运行

照片表定义:

CREATE TABLE `Photos` (
  `Id` int(11) NOT NULL AUTO_INCREMENT,
  `PersonId` int(11) NOT NULL,
  `Data` longblob NOT NULL,
  PRIMARY KEY (`Id`),
  KEY `FK_PersonId_IDX` (`photo_person_id`),
  CONSTRAINT `FK_PersonId` FOREIGN KEY (`PersonId`) REFERENCES `Persons` (`Id`)
          ON DELETE CASCADE ON UPDATE CASCADE
) ENGINE=InnoDB DEFAULT CHARSET=utf8;

应用程序本身的内存使用率非常低。增加innodb_buffer_pool_size确实会增加发生问题的时间(或导出的照片数量),与大小的增加成比例,但我不想为了能够导出这些图像而向服务器添加更多内存

在我看来,使用大型blob填充InnoDB缓冲池会导致这个问题,但据我所知,如果我确实想要选择所有这些blob,那么实际上没有办法防止这种情况发生,那么什么我可不可以做?我意识到我可能会增加超时但这只是一个糟糕的解决方案,显而易见的原因,我已经考虑将Photos表更改为MyISAM,我想这可以解决问题,但如果还有其他一些简单的解决方案,我宁愿不这样做。如果实际上没有办法解决这个问题,我也会对导出照片的完全替代解决方案持开放态度。

我真的不知道其他相关信息是什么,所以请在评论中询问任何其他细节。

1 个答案:

答案 0 :(得分:1)

不要使用function best1() { var ss = SpreadsheetApp.getActiveSpreadsheet(), sheet = ss.getSheetByName("Platform"), range = sheet.getDataRange(), values = range.getValues(); //Start loop from row 3 stoping at row 54 for (var i = 3; i < 54; i++) { //start loop from column 37 "AL" to 57 "BE" for (var j = 37; j < 57; j++) { //find all data in loops var data = values [i][j]; //find value in active row and column 34 "AI" var v1 = values [i][34] //find value in active row and column 35 "AJ" var v2 = values [i][35]; //find value in active row and column 36 "AK" var v3 = values [i][36]; //Compare active value to not null if (values [i ][34] !== "" ){ //Check for blank spot if (data === ""){ //Find blank spot and replace it with active value sheet.getRange(i+1, j+1).setValue(v1); //Re-call all data due to change values = range.getValues(); //Set active value to null sheet.getRange(i+1, 34+1).setValue(""); //Re-call all data due to change var v1 = values [i][34]; } } //Compare active value to not null if (values [i ][35] != ""){ //Check for blank spot if (data == ""){ //Find blank spot and replace it with active value sheet.getRange(i+1, j+1).setValue(v2); //Re-call all data due to change values = range.getValues(); //Set active value to null sheet.getRange(i+1, 35+1).setValue(""); //Re-call all data due to change var v2 = values [i][35]; } } //Start loop from row 3 stoping at row 54 for (var x = 3; x < 54; x++) { //start loop from column 37 "AL" to 57 "BE" for (var r = 37; r < 57; r++){ //Compare active value to not null if (values [i ][34] !== "" ){ //Compare active value if greater than lowest value if (v1 >= v3) //Compare lowest value to current data if (v3 == values [i][j]){ //Set active value to null sheet.getRange(i+1, 34+1).setValue(""); //Find blank spot and replace it with active value sheet.getRange(i+1, j+1).setValue(v1); //Re-call all data due to change values = range.getValues(); //Re-call all data due to change var v1 = values [i][34]; } } } //Compare active value to not null if (values [i ][35] !== "" ){ //Compare active value if greater than lowest value if (v2 >= v3){ //Compare lowest value to current data if (v3 === values [i][j]){ //Set active value to null sheet.getRange(i+1, 35+1).setValue(""); //Find blank spot and replace it with active value sheet.getRange(i+1, j+1).setValue(v2); //Re-call all data due to change values = range.getValues(); //Re-call all data due to change var v1 = values [i][35]; } } } } } } } ,它必须单步执行所有这些行才能到达您真正想要的10行。此外,如果添加/删除行,您可能会错过或复制一行。

取而代之的是remember where you left off

如果由于某种原因无法实现,那么使用“lazy eval”,其中只获取10个ID,而不是其余列。这是在子查询中。然后OFFSET返回表格以获得所需的其余列。