簡體   English   中英

MySQL-需要幫助來提高查詢性能

[英]MySQL - need help in improving query performance

最初的問題是基於將tx隔離設置為READ UNCOMMITTED的最佳方式,但是在提出一些建議之后,看來我最初的想法是不正確的。

DDL

CREATE TABLE `tblgpslog` (
    `GPSLogID` BIGINT(20) NOT NULL AUTO_INCREMENT,
    `DTSaved` DATETIME NULL DEFAULT NULL,
    `PrimaryAssetID` BIGINT(20) NULL DEFAULT NULL,
    `SecondaryAssetID` BIGINT(20) NULL DEFAULT NULL,
    `ThirdAssetID` BIGINT(20) NULL DEFAULT NULL,
    `JourneyType` CHAR(1) NOT NULL DEFAULT 'B',
    `DateStamp` DATETIME NULL DEFAULT NULL,
    `Status` VARCHAR(50) NULL DEFAULT NULL,
    `Location` VARCHAR(255) NULL DEFAULT '',
    `Latitude` DECIMAL(11,8) NULL DEFAULT NULL,
    `Longitude` DECIMAL(11,8) NULL DEFAULT NULL,
    `GPSFix` CHAR(2) NULL DEFAULT NULL,
    `Speed` BIGINT(20) NULL DEFAULT NULL,
    `Heading` INT(11) NULL DEFAULT NULL,
    `LifeOdometer` BIGINT(20) NULL DEFAULT NULL,
    `Extra` VARCHAR(20) NULL DEFAULT NULL,
    `BatteryLevel` VARCHAR(5) NULL DEFAULT '--',
    `Ignition` TINYINT(4) NOT NULL DEFAULT '1',
    `Radius` INT(11) NOT NULL DEFAULT '0',
    `GSMLatitude` DECIMAL(11,8) NOT NULL DEFAULT '0.00000000',
    `GSMLongitude` DECIMAL(11,8) NOT NULL DEFAULT '0.00000000',
    PRIMARY KEY (`GPSLogID`),
    UNIQUE INDEX `GPSLogID` (`GPSLogID`),
    INDEX `SecondaryUnitID` (`SecondaryAssetID`),
    INDEX `ThirdUnitID` (`ThirdAssetID`),
    INDEX `DateStamp` (`DateStamp`),
    INDEX `PrimaryUnitIDDateStamp` (`PrimaryAssetID`, `DateStamp`, `Status`),
    INDEX `Location` (`Location`),
    INDEX `DTSaved` (`DTSaved`),
    INDEX `PrimaryAssetID` (`PrimaryAssetID`)
)
COLLATE='latin1_swedish_ci'
ENGINE=InnoDB
AUTO_INCREMENT=153076364
;

原始查詢如下

SELECT L.GPSLogID, L.DateStamp, L.Status, Location, Latitude, Longitude, GPSFix, Speed, Heading, LifeOdometer, BatteryLevel, Ignition, L.Extra 
FROM tblGPSLog L 
WHERE PrimaryAssetID = 183 AND L.GPSLogID > 147694199
ORDER BY DateStamp ASC 
LIMIT 100;

"id","select_type","table","type","possible_keys","key","key_len","ref","rows","Extra"
"1","SIMPLE","L","index_merge","PRIMARY,GPSLogID,PrimaryUnitIDDateStamp,PrimaryAssetID","PrimaryAssetID,PRIMARY","9,8",\N,"96","Using intersect(PrimaryAssetID,PRIMARY); Using where; Using filesort"

這給幾個月前帶來了問題,經過一番調查后,我將查詢更改為以下內容,但現在的行為非常相似。

EXPLAIN SELECT GPSLogID, DateStamp, tmpA.Status, Location, Latitude, Longitude, GPSFix, Speed, Heading, LifeOdometer, BatteryLevel, Ignition, tmpA.Extra, 
PrimaryAssetID FROM (SELECT L.GPSLogID, L.DateStamp, L.Status, Location, Latitude, Longitude, GPSFix, Speed, Heading, LifeOdometer, 
BatteryLevel, Ignition, L.Extra, PrimaryAssetID 
FROM tblGPSLog L 
WHERE L.GPSLogID > 147694199) AS tmpA 
WHERE PrimaryAssetID = 183 
ORDER BY DateStamp ASC;

"id","select_type","table","type","possible_keys","key","key_len","ref","rows","Extra"
"1","PRIMARY","<derived2>","ALL",\N,\N,\N,\N,"5380842","Using where; Using filesort"
"2","DERIVED","L","range","PRIMARY,GPSLogID","PRIMARY","8",\N,"8579290","Using where"

感謝您的任何建議。

吉姆

我相信將tx隔離設置為READ UNCOMMITTED會阻止SELECT鎖定表。

您為什么會相信READ UNCOMMITTED可以實現?

默認情況下,除SERIALIZABLE以外,SELECT在所有隔離級別中均已處於非鎖定狀態。

也就是說,除非您使用FOR UPDATEFOR SHARE / LOCK IN SHARE MODE否則SELECT始終是非鎖定的。 使用SERIALIZABLE隔離級別時,SELECT隱式轉換為鎖定的SELECT FOR SHARE 參見https://dev.mysql.com/doc/refman/8.0/en/innodb-transaction-isolation-levels.html

我強烈建議不要使用READ UNCOMMITTED。 這不是一個好主意,因為您的事務可以讀取其他事務的未提交工作,這意味着您可以讀取不一致的數據(部分完成的事務)和幻象數據(最終回滾的事務的更改)。 這樣做沒有任何優勢,而且查詢返回錯誤結果的可能性很大。

是什么讓您認為鎖定是造成性能問題的原因? 您是否在慢查詢日志中觀察到鎖定時間增加了?

性能問題通常是由於查詢優化不佳或系統資源不足引起的。

如果您的數據庫在8年以上之后變慢,我猜想數據庫已經增長,直到活動數據集不再適合RAM。


發表您的評論:

有沒有工具或方法可以對此進行進一步調查? 我知道導致問題的查詢,只是無法確定原因

有許多調查工具和方法。 有關於此主題的書籍,例如高性能MySQL ,以及致力於創建性能監視工具的整個公司,例如PerconaVividCortex

如果不知道更多具體細節,我無法猜測一個建議。 如果您需要更多幫助,可以在上方編輯您的原始問題並添加:

  • 有問題的SQL查詢。
  • 遇到問題的查詢的EXPLAIN <query>的輸出。
  • 查詢所引用的每個表的SHOW CREATE TABLE <tablename>的輸出。 您可以在MySQL客戶端中運行此語句。

那是給初學者的。

您的陳述

SELECT在執行INSERT時會碰到表的情況很少見,即使這樣做,也不會造成任何重大問題。 僅在非高峰時段每周安排一次DELETE語句,

等同於“更改隔離模式無濟於事”。

我建議設置long_query_time=1並打開慢速日志。 稍后,使用pt-query-digest瀏覽慢日志,以查找一些“最差”的查詢。 然后讓我們討論改進它們。

更多

INDEX `PrimaryUnitIDDateStamp` (`PrimaryAssetID`, `DateStamp`,
INDEX `PrimaryAssetID`         (`PrimaryAssetID`)

其中第一個照顧第二個,因此第二個不必要。

PRIMARY KEY             (`GPSLogID`),
UNIQUE INDEX `GPSLogID` (`GPSLogID`),

PK是唯一鍵,因此請取下第二個。 額外的唯一索引會減慢插入速度並浪費磁盤空間。

在這種情況下,我認為沒有理由進行查詢和子查詢:

SELECT  GPSLogID, DateStamp, tmpA.Status, Location, Latitude,
        Longitude, GPSFix, Speed, Heading, LifeOdometer, BatteryLevel,
        Ignition, tmpA.Extra, PrimaryAssetID
    FROM  
        ( SELECT  L.GPSLogID, L.DateStamp, L.Status, Location, Latitude,
                  Longitude, GPSFix, Speed, Heading, LifeOdometer, BatteryLevel,
                  Ignition, L.Extra, PrimaryAssetID
            FROM  tblGPSLog L
            WHERE  L.GPSLogID > 147694199
        ) AS tmpA
    WHERE  PrimaryAssetID = 183
    ORDER BY  DateStamp ASC;

一對DECIMAL(11,8)加起來最多為12個字節,對於lat&lng來說是多余的。 看到為較小的選擇。

桌子的大小一直在增長,對嗎? 而且,當它變得如此龐大之后,性能會急劇下降嗎? 縮小數據類型以縮小表是一種方法,盡管是臨時解決方法。

Using intersect(PrimaryAssetID,PRIMARY) -幾乎總是比使用“索引合並相交”建立一個復合索引更好。

雖然

INDEX `PrimaryAssetID`         (`PrimaryAssetID`)

應該等於

INDEX `PrimaryAssetID`         (`PrimaryAssetID`, GPSLogID)

有些東西阻止了它。 建議您添加此2列復合索引。 也許很大一部分行具有PrimaryAssetID = 183 如果方便,請SELECT COUNT(*) FROM tblgpslog WHERE PrimaryAssetID = 183執行SELECT COUNT(*) FROM tblgpslog WHERE PrimaryAssetID = 183

您要從該日志中清除“舊”數據嗎? 如果是這樣,則最佳方法包括PARTITIONing 看到這個

暫無
暫無

聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.

 
粵ICP備18138465號  © 2020-2024 STACKOOM.COM