일반 텍스트 파일로 비슷한 상황을 설명했습니다.거대한 파일에서 많은 수의 패턴을 Grep합니다.. 많은 사람들이 내가 이 작업을 수행해야 한다고 말했기 때문에 이제 데이터를 sqlite 데이터베이스로 마이그레이션하고 있습니다.
약 10,000개의 패턴을 추출한 파일이 있습니다. 그런 다음 데이터베이스에 해당 스키마가 포함되어 있지 않은지 확인합니다. 그렇지 않은 경우 file
추가 처리를 위해 외부에 저장해야 합니다 .
for id in $(grep ^[0-9] keys); do
if [[ -z $(sqlite3 db.sqlite "select id from main where id = $id") ]]; then
echo $id >>file
fi
done
저는 SQL을 처음 접했기 때문에 이 작업을 수행하는 쉬운 방법을 찾을 수 없습니다. 또한 이 루프는 awk
위 URL에서 구현한 것보다 20배 느리기 때문에 쓸모가 없습니다.
데이터베이스가 크고 성장하고 있으며 이 루프를 매우 자주 실행하므로 더 빠르게 만들 수 있습니까?
답변1
sqlite
각 모드에 대해 데이터베이스에 다시 연결하는 프로그램의 새 인스턴스를 호출합니다. 정말 낭비입니다. 키를 찾는 쿼리를 작성한 다음 해당 쿼리를 실행해야 합니다. 데이터베이스 클라이언트는 대규모 쿼리를 실행하는 데 능숙합니다.
파일의 일치하는 줄에 keys
숫자만 포함된 경우 다음과 같이 쿼리를 작성할 수 있습니다.
{
echo 'select id from main where id in (';
<keys grep -x '[0-9][0-9]*' | # retain only lines containing only digits
sed -e '1! s/^/, /' | # add ", " at the beginning of every line except the first
echo ');'
} | sqlite3 db.sqlite
보다 일반적인 입력 데이터의 경우 텍스트 변환을 사용하여 하나의 대규모 쿼리를 작성하는 아이디어를 얻을 수 있습니다. 주의 깊은입력 확인;여기서 쿼리에 삽입한 내용이 구문적으로 유효한지 확인합니다. 위의 예에는 실제로 극단적인 경우가 있습니다. 파일에 일치 항목이 없으면 SQL 구문이 유효하지 않습니다. 파일에 일치 항목이 없으면 SQL 구문이 유효하지 않습니다. 가능하다면 이 상황을 처리해야 합니다. 특별히. null 사례를 처리하는 더 복잡한 코드는 다음과 같습니다.
<keys grep -x '[0-9][0-9]*' |
if read first; then {
echo 'select id from main where id in (' "$first"
sed -e 's/^/, /'
echo ');'
} | sqlite3 db.sqlite
fi
답변2
먼저 if
목록으로 바꾸었습니다. 사실 나는 [[]]
s를 s로 바꾼 []
다음 실행 dash
하거나 더 가벼운 것을 실행할 수도 있습니다 sh
. 이것은 모든 것을 삭제 for
하고 실행할 수 있을 만큼 간단해 보입니다 xargs
(항상 제가 선호하는 것, 더 나은 성능). 예를 들어 다음과 같습니다...
grep ^[0-9] keys | xargs -P0 -I '{id}' \
sh -c '[ -z "$(sqlite3 db.sqlite =\"select id from main where id = '{id}'\")" ] && \
echo '{id}' >> file'
내 탈출은 실패했을 가능성이 크지만, 이것이 당신에게 올바른 방향을 알려줄 것입니다. 적어도 병렬로 실행되기 때문에 이것이 더 빠르게 수행될 것이라고 생각합니다 -P
.
어떤 이유로 인해 크롤링 중이더라도 덤프된 sqlite 데이터베이스의 내용을 항상 볼 수 있습니다. 이 접근 방식을 취하면 아마도 스크립트를 작성하게 될 것입니다. 필요한 경우에만 고려하겠습니다.
답변3
ID를 새 테이블로 가져와 이를 사용하여 main
테이블을 쿼리합니다. 사용 후 테이블을 버리십시오.
{ echo id; grep '^[0-9]' keys; } |
sqlite3 database.db \
'CREATE TABLE ids ( id INTEGER UNIQUE )' \
'.import /dev/stdin ids' \
'SELECT * FROM main NATURAL JOIN ids' \
'DROP TABLE ids'
시험:
sqlite> .mode box
sqlite> SELECT * FROM main;
┌────┬─────────────────┐
│ id │ word │
├────┼─────────────────┤
│ 1 │ concessionaire │
│ 2 │ goniometrically │
│ 3 │ meshed │
│ 4 │ Celtic │
│ 5 │ guiltless │
│ 6 │ sclerodactylia │
│ 7 │ spiritism │
│ 8 │ ratchel │
│ 9 │ Bajau │
│ 10 │ semimineral │
└────┴─────────────────┘
$ cat keys
3
7
78
190
주어진 명령을 실행하면 다음이 출력됩니다( ID만 출력하는 id
대신 선택됨).*
3|meshed
7|spiritism