任何机构都可以帮助我理解SQL服务器中缓存的函数的执行计划吗?
任何在线资源?
MySQL中的EXPLAIN和DESC命令有什么区别?
这是我正在研究的查询之一的mysql解释计划.
+----+-------------+--------+-------+---------------+---------+---------+------+------+-------+
| id | select_type | table | type | possible_keys | key | key_len | ref | rows | Extra |
+----+-------------+--------+-------+---------------+---------+---------+------+------+-------+
| 1 | SIMPLE | table2 | index | NULL | PRIMARY | 4 | NULL | 6 | |
| 1 | SIMPLE | table3 | ALL | NULL | NULL | NULL | NULL | 23 | |
| 1 | SIMPLE | table1 | ALL | NULL | NULL | NULL | NULL …Run Code Online (Sandbox Code Playgroud) 我不时会遇到奇怪的MySQL行为.假设我有索引(type,rel,created),(type),(rel).像这样的查询的最佳选择:
SELECT id FROM tbl
WHERE rel = 3 AND type = 3
ORDER BY created;
Run Code Online (Sandbox Code Playgroud)
将是使用索引(type, rel, created).但MySQL的决定交叉索引(type)和(rel),并导致更坏更流畅.这是一个例子:
mysql> EXPLAIN
-> SELECT id FROM tbl
-> WHERE rel = 3 AND type = 3
-> ORDER BY created\G
*************************** 1. row ***************************
id: 1
select_type: SIMPLE
table: tbl
type: index_merge
possible_keys: idx_type,idx_rel,idx_rel_type_created
key: idx_type,idx_rel
key_len: 1,2
ref: NULL
rows: 4343
Extra: Using intersect(idx_type,idx_rel); Using where; Using filesort
Run Code Online (Sandbox Code Playgroud)
和相同的查询,但添加了一个提示:
mysql> EXPLAIN
-> SELECT id …Run Code Online (Sandbox Code Playgroud) mysql query-optimization sql-execution-plan database-indexes
UPDATE无论我是否更改了列中的值,Hibernate都会生成包含所有列的语句,例如:
tx.begin();
Item i = em.find(Item.class, 12345);
i.setA("a-value");
tx.commit();
Run Code Online (Sandbox Code Playgroud)
发表此UPDATE声明:
update Item set A = $1, B = $2, C = $3, D = $4 where id = $5
Run Code Online (Sandbox Code Playgroud)
因此列B,C,D会更新,而我没有更改它们.
比如,项目经常更新,所有列都被编入索引.问题是:将Hibernate部分优化为这样的事情是否有意义:
tx.begin();
em.createQuery("update Item i set i.a = :a where i.id = :id")
.setParameter("a", "a-value")
.setParameter("id", 12345)
.executeUpdate();
tx.commit();
Run Code Online (Sandbox Code Playgroud)
最让我困惑的是,EXPLAIN"未经优化"和"优化"查询版本的计划完全相同!
我有四张桌子; 两个用于当前数据,两个用于存档数据.其中一个归档表有数千万行.所有表都有几个窄索引,非常相似.
鉴于以下查询:
SELECT (SELECT COUNT(*) FROM A)
UNION SELECT (SELECT COUNT(*) FROM B)
UNION SELECT (SELECT COUNT(*) FROM C_LargeTable)
UNION SELECT (SELECT COUNT(*) FROM D);
Run Code Online (Sandbox Code Playgroud)
A,B和D执行索引扫描.C_LargeTable使用a seq scan,查询大约需要20秒才能执行.表D也有数百万行,但只有C_LargeTable大小的10%左右
如果我然后修改我的查询以使用以下逻辑执行,这足以缩小计数,我仍然得到相同的结果,使用索引并且查询大约需要5秒,或1/4的时间
...
SELECT (SELECT COUNT(*) FROM C_LargeTable WHERE idx_col < 'G')
+ (SELECT COUNT(*) FROM C_LargeTable WHERE idx_col BETWEEN 'G' AND 'Q')
+ (SELECT COUNT(*) FROM C_LargeTable WHERE idx_col > 'Q')
...
Run Code Online (Sandbox Code Playgroud)
当存在完美良好的索引并且存在覆盖主键以确保唯一性时,对于计数具有全表扫描的I/O开销是没有意义的.我对postgres的理解是a PRIMARY KEY不像SQL Server集群索引那样确定排序,但它隐式创建了一个btree索引来确保唯一性,我认为这应该比全表扫描要求的I/O少得多.
这可能是我在C_LargeTable中组织数据时可能需要执行的优化的指示吗?
我有一个简单的脚本.
IF OBJECT_ID('dbo.Customers', 'U') IS NOT NULL
DROP TABLE dbo.Customers;
GO
CREATE TABLE dbo.Customers
(
custid INT NOT NULL,
companyname VARCHAR(125) NOT NULL,
phone VARCHAR(120) NOT NULL,
address VARCHAR(150) NOT NULL
);
INSERT INTO dbo.Customers
(custid, companyname, phone, address)
VALUES (1, 'cust 1', '(111) 111-1111', 'address 1'),
(2, 'cust 2', '(222) 222-2222', 'address 2'),
(3, 'cust 3', '(333) 333-3333', 'address 3'),
(4, 'cust 4', '(444) 444-4444', 'address 4'),
(5, 'cust 5', '(555) 555-5555', 'address 5');
IF OBJECT_ID('dbo.CustomersStage', 'U') IS NOT …Run Code Online (Sandbox Code Playgroud) 我在Linux上安装了SQL Server.它是从Microsoft的repos安装的,如下所述:https: //docs.microsoft.com/en-us/sql/linux/quickstart-install-connect-ubuntu
在MySql中,我曾经EXPLAIN在查询前写过,看看执行计划.在SQL Server中,它似乎不起作用.但我没有安装工作室程序,只有SQL Server和sqlcmd工具.
如何在Linux上的SQL Server中查看查询的执行计划?
linux sql-server sql-execution-plan sql-operations-studio sql-server-linux
我遇到的问题是,索引的查询拒绝使用索引,因为它没有足够的选择性(假设有1.3亿行中的60个符合条件),因此决定使用seqscan.
我面临的问题是seqscan在这种情况下真的不是最好的选择,由于某些原因它获得了非常好的分数,但事实是seqscan只有在之前被查询并且它可以加载所有内容时才能快速运行来自缓冲区/缓存.
与seqscan相比,索引扫描可能稍微慢一点,如果它们的两个都在缓冲区上,但这很少发生,当两个查询都很冷时,索引扫描仍然更快(ms vs秒).
请注意,索引扫描是优越的,因为我正在使用限制子句,因此它应该能够非常快速地获取这几行.
我已将统计值设置为1000(默认值为100)并且为了以防真空吸尘,但是相同的故事.
TLDR:Seq扫描与低选择性索引上的索引扫描,seqscan是首选,但规划者是错误的,seqscan只有在缓存时才会更好,否则会更糟.
查询和计划,请注意索引一是从缓冲区加载而seqscan不完全.
explain (analyze, buffers)
select *
from identities_identity
where email_domain = 'live.com'
limit 100
'Limit (cost=0.00..63.50 rows=100 width=573) (actual time=75215.573..75215.640 rows=100 loops=1)'
' Buffers: shared hit=75113 read=588870'
' -> Seq Scan on identities_identity (cost=0.00..2980008.00 rows=4692733 width=573) (actual time=75215.571..75215.604 rows=100 loops=1)'
' Filter: ((email_domain)::text = 'live.com'::text)'
' Rows Removed by Filter: 54464136'
' Buffers: shared hit=75113 read=588870'
'Planning time: 0.097 ms'
'Execution time: 75215.675 ms'
'Limit (cost=0.57..187.26 rows=100 width=573) (actual time=0.027..0.090 rows=100 loops=1)'
' …Run Code Online (Sandbox Code Playgroud) 从PostgreSQL文档中的示例:
EXPLAIN SELECT * FROM tenk1 WHERE unique1 < 100 AND stringu1 = 'xxx';
QUERY PLAN
------------------------------------------------------------------------------
Bitmap Heap Scan on tenk1 (cost=5.04..229.43 rows=1 width=244)
Recheck Cond: (unique1 < 100)
Filter: (stringu1 = 'xxx'::name)
-> Bitmap Index Scan on tenk1_unique1 (cost=0.00..5.04 rows=101
width=0)
Index Cond: (unique1 < 100)
Run Code Online (Sandbox Code Playgroud)
我纠正了吗
首先对第一个条件的所有行执行位图索引扫描,并且
然后在返回的行上,执行第二个条件的位图堆扫描?
由于位图索引扫描已检查unique1 <100上的索引条件,为什么在Bitmp堆扫描中再次在相同条件下"重新检查条件"?"Recheck Cond"是什么意思?
我不确定我是否理解这篇相关文章https://dba.stackexchange.com/questions/106264/recheck-cond-line-in-query-plans-with-a-bitmap-index-scan
谢谢.
postgresql ×4
mysql ×3
sql-server ×3
indexing ×2
performance ×2
t-sql ×2
describe ×1
function ×1
hibernate ×1
jpa ×1
linux ×1
seq ×1
sql-function ×1