标签: query-performance

Should I split timestamp parts into separate columns?

I am building a PostgreSQL database and I have created a timestamp table, where the primary key is the timestamp itself (e.g. id: Fri Apr 13 2018 15:00:19). The database is supposed to be later migrated to a data warehouse, from which analytics will be extracted.

At this point, I am wondering whether it is beneficial to add extra columns to the timestamp table, containing the parsed metrics such as the example below, or have a single table with …

postgresql performance database-design optimization timestamp query-performance

2
推荐指数
2
解决办法
301
查看次数

了解何时从查询/计划中删除 Order By 或 Sort 运算符

当我正在阅读和理解时,如果匹配索引以支持查询的键列以相同的方式排序,则需要避免 SQL 查询中不需要的 ORDER BY。

对于下面的数据库测试模式——

CREATE PARTITION FUNCTION DemoPartitionFunction (datetime)
AS RANGE RIGHT
FOR VALUES (DATEADD(dd, DATEDIFF(dd, 0, GETUTCDATE()), -7),
            DATEADD(dd, DATEDIFF(dd, 0, GETUTCDATE()), -6),
            DATEADD(dd, DATEDIFF(dd, 0, GETUTCDATE()), -5),
            DATEADD(dd, DATEDIFF(dd, 0, GETUTCDATE()), -4),
            DATEADD(dd, DATEDIFF(dd, 0, GETUTCDATE()), -3),
            DATEADD(dd, DATEDIFF(dd, 0, GETUTCDATE()), -2),
            DATEADD(dd, DATEDIFF(dd, 0, GETUTCDATE()), -1),
            DATEADD(dd, DATEDIFF(dd, 0, GETUTCDATE()), 0),
            DATEADD(dd, DATEDIFF(dd, 0, GETUTCDATE()), 1),
            DATEADD(dd, DATEDIFF(dd, 0, GETUTCDATE()), 2),
            DATEADD(dd, DATEDIFF(dd, 0, GETUTCDATE()), 3),
            DATEADD(dd, DATEDIFF(dd, 0, GETUTCDATE()), 4),
            DATEADD(dd, DATEDIFF(dd, 0, GETUTCDATE()), …
Run Code Online (Sandbox Code Playgroud)

performance index sql-server query-performance performance-tuning

2
推荐指数
1
解决办法
85
查看次数

如何将 CASE 表达式重写为短路评估

我想知道是否有任何方法可以重写查询中的表达式(只是表达式,而不是整个查询)以短路 THEN 阶段的无用评估?

演示数据:

CREATE TABLE #Docs (
    ID INT NOT NULL
    ,DocType TINYINT NOT NULL
    );

CREATE TABLE #DocsItems (
    IDDocs INT NOT NULL
    ,Amount NUMERIC(19,6)
    );

INSERT INTO #Docs(ID, DocType) VALUES(1,1),(2,1),(3,2),(4,2),(5,2),(6,2);
INSERT INTO #DocsItems(IDDocs,Amount) VALUES(3,50.),(3,25.),(3,33.),(4,44.),(4,123.),(6,11.);
Run Code Online (Sandbox Code Playgroud)

主题查询:

SELECT
    -- expression
    SumAmount = CASE 
                    WHEN D.DocType <> 1 THEN (SELECT SUM(Amount) FROM #DocsItems WHERE IDDocs = D.ID)
                END
FROM #Docs D
WHERE D.DocType = 1  -- so CASE condition evaluates to False
Run Code Online (Sandbox Code Playgroud)

查询计划: 在此处输入图片说明

如果我将查询(故意)重写为:

SELECT
    -- expression
    SumAmount = CASE …
Run Code Online (Sandbox Code Playgroud)

performance sql-server execution-plan query-performance

2
推荐指数
1
解决办法
382
查看次数

带有文字的 SQL Server 查询立即运行,使用变量需要几分钟

对于运行 ERP 系统的 Azure 上的 Microsoft SQL Server 2017 (RTM-CU20)(因此不能更改此处的代码)。

我有一个超过 4200 万行的表。这是一个机器操作统计跟踪表。用户按设备、日期、班次和统计类型(运行小时数、吨数等)输入运行统计数据。

该表具有这样的主键结构(请不要对 nchar 而不是 nvarchar 或将日期存储为字符串发表评论,这就是 ERP 供应商提供它的方式,这正是我必须使用的):

equip nchar(12)       This is a 12 character equipment number
key_type nchar(1)     One of two values E for equipment or G - always E here
shift_seq_no nchar(2) Sequence of shifts (usually 00 or 01)
stat_date nchar(8)    Date, YYYYMMDD
stat_type nchar(2)    A code for stat type, OH here (operating hours)
trc_seq_no nchar(3)   A sequence number for when there's more than one entry …
Run Code Online (Sandbox Code Playgroud)

sql-server optimization query-performance

2
推荐指数
1
解决办法
295
查看次数

升级到 MySQL 8 后的性能问题

更新(tl;博士;)

我在这里提交了一个错误报告:https : //bugs.mysql.com/bug.php?id=99593已被确认并提供了解决方法。有关详细信息,请参阅下面的答案。


某些查询似乎在 MySQL 8.0.20 下挣扎,我想知道是否有人可以指出一些可能的解决方案。目前我已经启动并运行了旧服务器,仍在 5.7.30 上运行,因此很容易对性能结果进行 A/B。两台服务器都有 32GB 的 RAM,几乎相同的配置,所有表都是 InnoDB。以下是一些(相关)设置:

innodb_flush_log_at_trx_commit = 0
innodb_flush_method            = O_DIRECT
innodb_file_per_table          = 1
innodb_buffer_pool_instances   = 12
innodb_buffer_pool_size        = 16G
innodb_log_buffer_size         = 256M
innodb_log_file_size           = 1536M
innodb_read_io_threads         = 64
innodb_write_io_threads        = 64
innodb_io_capacity             = 5000
innodb_thread_concurrency      = 0
Run Code Online (Sandbox Code Playgroud)

示例 1:

SELECT DISTINCT vehicle_id, submodel_id, store_id
FROM product_to_store pts
    JOIN product_to_vehicle ptv USING (product_id)
WHERE vehicle_id != 0 AND pts.store_id = 21;
Run Code Online (Sandbox Code Playgroud)

此查询产生以下解释:

MySQL 8.0.20(查询需要 24 秒):

+----+-------------+-------+------------+------+-------------------------------------------+--------------------------+---------+----------------+--------+----------+------------------------------+ …
Run Code Online (Sandbox Code Playgroud)

mysql-5.7 mysql-8.0 query-performance

2
推荐指数
1
解决办法
1092
查看次数

为什么创建索引和运行查询比没有它运行查询更快?

我有几百万行的表。它包含来自外部服务的日志,所以我决定不对其进行索引(大量插入,稀疏读取)。

当我运行从没有索引的表中读取的查询时,它需要(不出所料)很长时间。

但是,当我创建索引并运行查询然后删除索引时,速度要快得多(即使创建和删除索引也是如此)。

为什么创建临时索引更快,而不是让 SQL Server 做它的事情?这似乎不直观(为什么 SQL Server 不自己创建索引?)。这种方法有什么缺点吗?


有问题的查询看起来像这样,但我认为它不一定相关,因为我在其他地方也看到了类似的行为。

    UPDATE Device
    SET Col1 = l.Col1
        ,Col2 = l.Col2
        ,Col3 = l.Col3
    FROM dbo.Device
        OUTER APPLY (
            SELECT MAX(Id) AS [Id]
            FROM dbo.Logs 
            WHERE Logs.Device_FK = Device.Id
            GROUP BY Logs.Device_FK
        ) lastLog
        OUTER APPLY (
            SELECT Col1, Col2, FORMAT(Col3) AS "Col3"
            FROM dbo.Logs
            WHERE Logs.Id = lastLog.Id
        ) l
Run Code Online (Sandbox Code Playgroud)

sql-server sql-server-2017 query-performance

2
推荐指数
1
解决办法
317
查看次数

不使用 min() max() 获取选择的第一条和最后一条记录

我的能量计每分钟将(累计)消耗写入 db。为了获得我今天的消费,我使用:

SELECT
  (MAX(energy_kwh) - MIN(energy_kwh)) AS kwh_today
FROM logging.main_meter
WHERE DATE_FORMAT(strtime, '%Y-%m-%d') = CURDATE();
Run Code Online (Sandbox Code Playgroud)

问题是: max() 和 min() 似乎大大减慢了查询速度。我在列中添加了一个键,energy_kwh但没有帮助。我敢打赌有更好的方法来获得计算的第一个和最后一个记录。

表格(实际上要大得多,约 130 列,所以我将其缩小到相关部分):

CREATE TABLE 'main_meter` 
( 
  id int(11) NOT NULL AUTO_INCREMENT, 
  timestamp int(11) DEFAULT NULL, 
  strtime datetime DEFAULT NULL, 
  energy_kwh double unsigned DEFAULT '0', 
) ENGINE=InnoDB AUTO_INCREMENT=1717655 DEFAULT CHARSET=latin1;
Run Code Online (Sandbox Code Playgroud)

mysql query-performance

2
推荐指数
1
解决办法
766
查看次数

缓慢的并行 SQL Server 查询,串行几乎是即时的

我有一个 SQL Server 查询如下(混淆):

UPDATE  [TABLE1]
SET     [COLUMN1] = CAST('N' AS CHAR(1))
FROM    [TABLE1]
WHERE   (COLUMN1 = '2' AND COLUMN2 IN('VAL1', 'VAL2', 'VAL3')) OR 
        (COLUMN1 <> 'N' AND (
                                    SELECT  COUNT(*)
                                    FROM    TABLE2 wle
                                            JOIN TABLE3 wl 
                                                    ON wl.COLUMN3 = wle.COLUMN3
                                    WHERE   TABLE1.COLUMN4 = wle.COLUMN4 AND 
                                            (wl.COLUMN5 = '1' OR wl.COLUMN6 = '1') AND 
                                            wle.COLUMN7 = (
                                                            SELECT  MIN(alias.COLUMN7)
                                                            FROM    TABLE2 AS alias
                                                            WHERE   TABLE1.COLUMN4 = alias.COLUMN4
                                                            )
                                ) > 0
                                            
        )
Run Code Online (Sandbox Code Playgroud)

我们刚刚将我们的(测试)服务器从 SQL Server 2014 SP3 升级到 SQL Server …

parallelism sql-server-2016 query-performance

2
推荐指数
1
解决办法
206
查看次数

提高大表中MySql查询性能

我有一个 MySql 数据库,用于存储来自应用程序的事件,自从我们创建它以来,我们只插入和选择数据,我们从未删除任何行。我不是数据库管理员,我的组织中没有数据库管理员,所以如果我遗漏了一些基本的东西,请多多包涵。数据库有一个像这样的表:

CREATE TABLE `eventlogs` (
  `Id` int(11) NOT NULL AUTO_INCREMENT,
  `LogType` int(11) NOT NULL,
  `ProductId` longtext,
  `Username` varchar(128) CHARACTER SET utf8 DEFAULT NULL,
  `ClientVersion` longtext,
  `Message` longtext,
  `Referrer` longtext,
  `UserAgent` longtext,
  `CreatedDate` datetime NOT NULL,
  PRIMARY KEY (`Id`),
  KEY `IX_LogType` (`LogType`),
  KEY `IX_CreatedDate` (`CreatedDate`),
  KEY `IX_Username` (`Username`)
) ENGINE=InnoDB AUTO_INCREMENT=180712975 DEFAULT CHARSET=latin1;
Run Code Online (Sandbox Code Playgroud)

这曾经非常有效,但它达到了几乎不可能运行任何查询的程度,它们需要超过 15 分钟,有时甚至更多!这是我们运行的典型查询:

SELECT * FROM customily_logs.eventlogs
    WHERE CreatedDate > '2020-06-01'
      and Username = 'myuser'
      and LogType = 3
Run Code Online (Sandbox Code Playgroud)

这是查询的执行计划:

{
  "query_block": {
    "select_id": 1,
    "cost_info": …
Run Code Online (Sandbox Code Playgroud)

mysql innodb mysql-5.7 query-performance

2
推荐指数
1
解决办法
70
查看次数

我怎样才能加速这个 mysql (mariadb) 查询?

我用下面的查询平均每分钟大约 1000 次查询。大多数查询将保持不变,但日期、小时、分钟和 itemName(在本例中为 2021-06-02, 10, 30 和“football”)。我已经切换了各个部分,这似乎是性能的最佳顺序。我怀疑使用不同函数的查询可能更适合性能,但我还没有弄清楚。

SELECT  DatetimeRecorded, itemName, field1, field2, field3
    FROM  StoreData.data
    WHERE  DatetimeRecorded BETWEEN '2021-06-02' - INTERVAL 30 DAY
                                AND '2021-06-02' - INTERVAL 1 DAY
      AND  itemName = 'football'
      and  HOUR(DatetimeRecorded) = 10
      and  MINUTE(DatetimeRecorded) <= 30 
Run Code Online (Sandbox Code Playgroud)

在示例时间限制下,数据库中“足球”的频率每天只会出现一次,这意味着此查询和其他类似查询将返回最多 30 行,即每天 1 行。

以更易读的格式,我希望更有效地做的是“选择 2021-06-02 之前的 30 天,其中时间在 10:00 到 10:30 之间,项目是足球”

附加信息

  • 查询正在 mariadb Ver 15.1 Distrib 10.3.29-MariaDB 上运行,用于 debian-linux-gnu (x86_64) 使用 readline 5.2
  • 数据库大约有五十万个条目
  • 大约有 5000 个唯一的 itemNames

这是输出显示创建表

 | Data | CREATE TABLE …
Run Code Online (Sandbox Code Playgroud)

mysql mariadb query-performance

2
推荐指数
1
解决办法
515
查看次数