我必须通过调整基本的PostgreSQL服务器配置参数来优化查询.在文档中,我遇到了work_mem参数.然后我检查了如何更改此参数会影响我的查询的性能(使用sort).我用各种work_mem设置测量了查询执行时间,非常失望.
我执行查询的表包含10,000,000行,并且有430 MB的数据要排序.(Sort Method: external merge Disk: 430112kB).
用work_mem = 1MB,EXPLAIN输出是:
Total runtime: 29950.571 ms (sort takes about 19300 ms).
Sort (cost=4032588.78..4082588.66 rows=19999954 width=8)
(actual time=22577.149..26424.951 rows=20000000 loops=1)
Sort Key: "*SELECT* 1".n
Sort Method: external merge Disk: 430104kB
Run Code Online (Sandbox Code Playgroud)
用work_mem = 5MB:
Total runtime: 36282.729 ms (sort: 25400 ms).
Sort (cost=3485713.78..3535713.66 rows=19999954 width=8)
(actual time=25062.383..33246.561 rows=20000000 loops=1)
Sort Key: "*SELECT* 1".n
Sort Method: external merge Disk: 430104kB
Run Code Online (Sandbox Code Playgroud)
用work_mem …
我使用一个包含两个简单查询的小事务:select和update:
SELECT * FROM XYZ WHERE ABC = DEF
Run Code Online (Sandbox Code Playgroud)
和
UPDATE XYZ SET ABC = 123
WHERE ABC = DEF
Run Code Online (Sandbox Code Playgroud)
事务通常由两个线程启动,并且取决于隔离级别发生死锁(RepeatableRead,Serialization).两个事务都尝试读取和更新完全相同的行.我想知道为什么会这样.导致死锁的查询顺序是什么?我已经读过一些关于锁(共享,独占)以及每个隔离级别锁定的持续时间,但我仍然不完全理解......
我甚至准备了一个总是导致死锁的简单测试.我查看了SSMS和SQL Server Profiler中的测试结果.我开始第一次查询,然后立即开始第二次.
第一个查询:
SET TRANSACTION ISOLATION LEVEL SERIALIZABLE
BEGIN TRANSACTION
SELECT ...
WAITFOR DELAY '00:00:04'
UPDATE ...
COMMIT
Run Code Online (Sandbox Code Playgroud)
第二个查询:
SET TRANSACTION ISOLATION LEVEL SERIALIZABLE
BEGIN TRANSACTION
SELECT ...
UPDATE ...
COMMIT
Run Code Online (Sandbox Code Playgroud)
现在我无法向您显示详细的日志,但它看起来不那么像这样(我很可能错过了Lock:死锁等等):
(1) SQL:BatchStarting: First query
(2) SQL:BatchStarting: Second query
(3) Lock:timeout for second query
(4) Lock:timeout for first query
(5) Deadlock graph
Run Code Online (Sandbox Code Playgroud)
如果我理解了锁,在(1)第一个查询采用共享锁(执行SELECT),然后进入休眠状态并保持共享锁直到事务结束.在(2)中,第二个查询也采用共享锁(SELECT),但在同一行上存在共享锁时不能采用独占锁(UPDATE),这会导致Lock:timeout.但我无法解释为什么发生第二次查询的超时.可能我不太了解整个过程.任何人都能给出一个很好的解释吗?
我没有注意到使用ReadCommitted的死锁,但我担心它们可能会发生.你推荐什么解决方案?
我有一个函数返回调用此函数的对象的修改副本.我经常这样做:
obj = obj.Foo(param);
Run Code Online (Sandbox Code Playgroud)
不要问为什么,我只需要.但有时我(和其他人)忘记分配功能结果,这样做:
obj.Foo(param);
Run Code Online (Sandbox Code Playgroud)
这反复导致耗时的调试.
每次没有将功能结果分配给变量时,有没有办法显示警告或错误?或者其他任何建议如何解决这个问题?
我最近一直在为基于 C 的语言编写解析器。我正在使用 CUP(Java 的 Yacc)。
我想实施“词法分析器黑客”(http://eli.thegreenplace.net/2011/05/02/the-context-sensitive-of-c%E2%80%99s-grammar-revisited/ 或 https:/ /en.wikipedia.org/wiki/The_lexer_hack),以区分 typedef 名称和变量/函数名称等。要启用与之前声明的类型相同名称的变量(来自第一个链接的示例):
typedef int AA;
void foo() {
AA aa; /* OK - define variable aa of type AA */
float AA; /* OK - define variable AA of type float */
}
Run Code Online (Sandbox Code Playgroud)
我们必须引入一些新的产生式,其中变量/函数名称可以是IDENTIFIER或TYPENAME。这就是困难发生的时刻——语法冲突。
我试图不将这种凌乱的 Yacc 语法用于 gcc 3.4 ( http://yaxx.googlecode.com/svn-history/r2/trunk/gcc-3.4.0/gcc/c-parse.y ),但这次我不知道如何自己解决冲突。我看了一下 Yacc 语法:
declarator:
after_type_declarator
| notype_declarator
;
after_type_declarator:
...
| TYPENAME
;
notype_declarator:
...
| IDENTIFIER
;
fndef:
declspecs_ts setspecs declarator
// …Run Code Online (Sandbox Code Playgroud) 我有表示 json 的字符串,其中字段名称和值括在单引号中,例如{'name': 'Grzegorz', 'age': 123}。假设我在postgres数据库中还有一个表:
CREATE TABLE item (
metadata jsonb
);
Run Code Online (Sandbox Code Playgroud)
我正在尝试使用 JOOQ 插入行。JOOQ 生成以下语句:
insert into Item values('{''name'': ''Grzegorz'', ''age'': 123}'::jsonb);但抛出错误:
ERROR: invalid input syntax for type json
LINE 1: insert into Item values('{''name'': ''Grzegorz'', ''age'': 1...
Token "'" is invalid.
JSON data, line 1: {'...
Run Code Online (Sandbox Code Playgroud)
是否有可能插入名称用单引号'而不是双引号括起来的 json ",或者我应该将其全部转换'为"?
提前致谢!
格热戈日
我正在编写集成JUnit测试.我的任务是测试本地服务器的响应是否正确.所提到的服务器将要分析的页面的地址作为GET参数(例如:) localhost:8000/test?url=http://www.example.com.
为了避免依赖于www.example.com,我想从这个特定的测试开始我自己的jetty服务器,它始终提供相同的内容.
private static class MockPageHandler extends AbstractHandler {
public void handle(String target,Request baseRequest, HttpServletRequest request,
HttpServletResponse response)
throws IOException, ServletException {
response.setContentType("text/html; charset=utf-8");
response.setStatus(HttpServletResponse.SC_OK);
final String responseString = loadResource("index.html");
response.getWriter().write(responseString);
baseRequest.setHandled(true);
}
}
public void test() throws Exception {
final int PORT = 8080;
final Server server = new Server(PORT);
server.setHandler(new MockPageHandler());
server.start();
final ContentResponse response =
client.newRequest("http://localhost:8000/test?url=http://localhost:8080").send();
/* some assertions. */
server.stop();
server.join();
}
Run Code Online (Sandbox Code Playgroud)
每次执行此测试时,都不会调用handle方法MockPageHandler.你有什么建议为什么这不起作用?
PS当我删除server.stop()并在浏览器类型中http://localhost:8080显示正确的页面.
我想用single打印数组元素printf.该数组很小(例如最多10个元素),但每次我可能必须打印不同数量的第一个数组元素.
我知道我可以这样做:
count = how_many_first_elements_i_need_this_time();
printf("array elements: ");
for (i = 0; i < count; ++i)
printf("%d ", array[i]);
printf("\n");
Run Code Online (Sandbox Code Playgroud)
但是printf,我认为这可能会导致不同线程同时执行的几个输出交错.
我可以编写巨大的开关来处理所有可能的情况,但它很难看.
还有其他建议吗?
我在使用许多进程与数据库交互时遇到了一些奇怪的应用程序行为。我正在使用Linux。
我有自己的实现,QueryExecutor它在其生命周期内使用单个连接:
class QueryExecutor(object):
def __init__(self, db_conf):
self._db_config = db_conf
self._conn = self._get_connection()
def execute_query(self, query):
# some code
# some more code
def query_executor():
global _QUERY_EXECUTOR
if _QUERY_EXECUTOR is None:
_QUERY_EXECUTOR = QueryExecutor(some_db_config)
return _QUERY_EXECUTOR
Run Code Online (Sandbox Code Playgroud)
Query Executor实例化后永远不会被修改。
最初只有一个进程,它时不时会 fork ( os.fork()) 几次。新进程是执行一些任务然后退出的工作进程。每个工作人员调用query_executor()都能够执行 SQL 查询。
我发现sql查询经常返回错误的结果(似乎有时sql查询结果返回到错误的进程)。唯一合理的解释是所有进程共享相同的sql连接(根据MySQLdb文档:threadsafety = 1线程可以共享模块,但不能共享连接)。
我想知道是哪种操作系统机制导致了这种情况。据我所知,在Linux上,当进程分叉时,父进程的页面不会被复制给子进程,它们由两个进程共享,直到其中一个进程尝试修改某些页面(写入时复制)。正如我之前提到的,QueryExecutor对象在创建后保持不变。QueryExecutor我想这就是所有进程使用相同实例并因此使用相同 sql 连接的原因。
我是对的还是我错过了什么?你有什么建议吗?
提前致谢!
格热戈日