Quantcast
Channel: Sybase – Jason L. Froebe – Tech tips and How Tos for Fellow Techies
Viewing all 102 articles
Browse latest View live

SAP Sybase ASE: Unable to start ASE when getting “No unlocked logins with permission ‘…’ were found”? SOLVED

$
0
0

Have you received SAP Sybasethe error “No unlocked logins with permission ‘…’ were found” when attempting to start ASE?

00:0002:00000:00001:2014/03/14 08:51:04.87 server  Database 'master' is now online.
server  The transaction log in the database 'master' will use I/O size of 2 Kb.
server  No unlocked logins with permission '200' were found.
kernel  ueshutdown: exiting
kernel  Main thread performing final shutdown.
kernel  Network and device connection limit is 65519.
kernel  Encryption provider initialization succeeded on engine 1.
kernel  Thread 3 (LWP 41877545) of Threadpool syb_default_pool online as engine 1
kernel  Blocking call queue shutdown.
08:51:05.03 kernel  SySAM: Checked in license for 2 ASE_CORE

This message is the result of specifying the “-n” in the RUN server file for ASE.

-n system_privilege, –permission-logins – specifies the system privilege name so that a list of login accounts with this system privilege is printed into log file. – From Logging in to a locked-out Adaptive Server

When the “-n” is specified, it acts very similar to “-p” in the sense that ASE will make the change and shutdown. In this case, it would print the logins that have the system privilege of “200″ then shutdown.


SAP Sybase ASE 16.0 major features

$
0
0

Sybase .. er… SAP will be releasing Adaptive Server Enterprise 16 within in the next few months (currently expected in Q2 2014). SAP has made the ASE 16.0 manuals available.

Kevin Sherlock sums up the major new features quite well:

  • create or replace functionality
  • multiple triggers
  • monitoring threshold based events
  • configuration tracking history
  • partition level locking
  • log space usage tracking
  • CIS to HANA

While the number of major features may be a bit lacking on first glance to justify being a major release, Jeff Tallman of SAP provides a bit of reasoning on what was really changed:

Hidden under the covers of ASE 16 is a lot of rewrites to spinlock areas of code – so, while you are seeing what looks to be a scattering of features, the main work was done in scaling and eliminating contention – both on high core counts as well as lower core counts – the later especially with proc cache and ELC configuration – as well as log semaphore contention and eliminating the problem of buffer unpinning. Some of these changes required linking in machine code – which means only supporting current releases of certain platforms/OS’s – which by itself often dictates a new platform number. However, there are a number of new features – if you read the NFG, you can see a laundry list – one of which may or may not be mentioned there is HADR mode – which more tightly integrates ASE & SRS – not only is there a synchronous RepAgent (requires an new SRS SP to be launched later), standby ASE is readonly for normal users (ASE actually detects it is standby – and unless you are a privileged user such as RS maint or sa_role, writes are blocked), but ASE also now supports client failover from primary to standby ASE without OpenSwitch – in short term, available for Business Suite – later this year (perhaps) custom apps.

However, with regard to Full Database Encryption…..from a data security standpoint, you can think of it as filling a gap between column level encryption and standard MAC/DAC controls – especially with predicated permissions in the mix. Remember, in column level encryption, we decrypted data at the materialization stage (and encrypted it in normalization) which meant that the data was encrypted both in memory as well as on disk. This was important, because, when you have database users with different access requirements – and especially if you want to keep DBA’s from seeing the data, you need to encrypt the data in memory as well as on disk – and with different users/different requirements, you also need to be able to encrypt different columns with different keys. As a result of encryption, some common database performance techniques – such as leaf/range scans on encrypted cols – were penalized as the index was sorted by the encrypted value (otherwise, it would be security hole) – and no real secure encryption techniques exist that would preserve the lexigraphical sequence. As a result, often times a different index was used for the query or if that index was selected, it was a full leaf scan followed by decryption & sorting – quite a bit of overhead compared to the unencrypted leaf scan. Of course, Encrypted Columns took a bit of effort to set up as someone had to go through and identify every column of sensitive data, determine which Column Encryption Key to use and who should have access – some planning.

Encrypted Columns = data at rest and in memory fully encrypted – and only select designated users could see the data – others saw a default literal value.

Full Database Encryption is intended to solve the problem of ensuring the data at rest is encrypted, but sort of assumes that all legitimate users of the database have the same access rights to the data. Since all users have the same access rights, there is no need to encrypt in memory, use different keys for different columns, etc. As a result, the encryption happens just prior to being written to disk – or just after being read from disk – and on a page basis vs. individual column basis. As a result, index key values, etc. are in their normal sorted order – meaning there is no penalty for leaf scans/range scans any more. Yes, the PIOs may take a slight bit longer but I would be willing to wager we could encrypt the data far faster than traditional disk-based storage can either write it to disk or read it from disk. The time aspect may be very very slightly noticeable on large physical read driven queries. Of course, encryption does use CPU – that might be more noticeable – depending on how much physical IO you are doing. However, since most apps operate on 95%+ cache hit rates, it might not be that noticeable. Remember as well, for write intensive apps, it is often not your SPID doing the writes – it is the HK Wash, checkpoint, someone else pushing your page through wash marker, etc. Keep in mind that one of the drivers for this was SAP ERP applications – where performance is extremely critical due to the way the applications tend to operate (a lot of client side joins to avoid temp tables due to vendor incompatibilities with respect to tempdb). As a result, performance was a key consideration. Level of effort for implemenation is minimal – set up your keys and encrypt the database. Voila!

Full Database Encryption = data at rest fully encrypted – all legitimate users have access.

Hopefully, this not only addresses the speed question, but also the differences. — Jeff Tallman in response to ASE 16: When and what major features?

SAP has overhauled ASE bringing it up to modern performance and scalability. It’s far too early to determine whether the rebuilt engine will live up to the our expectations.

SAP SYBASE IQ 16.0 SP3 MANUALS FIXED TO WORK WITH TABLET/PHONE PDF READERS LIKE ALDIKO

$
0
0

Aldiko Book Reader Premium Full v2.2.3.apkMany PDF readers for smart phones (Android/iphone) and tablets manage the pdf files Calibre_Logobased solely on the Title and Author fields in the PDF file. While for this is fine for your average book, it is not all that helpful with manuals that tend to have abbreviated or no data in the title/author fields. In the case of the manuals for Sybase IQ, I’m unable to load the manuals for say v15.4 and v16.0 as they have the same Title/Author data.

How to fix? Easy. Go get Calibre. Drop the PDF files on to the running Calibre. Edit them by hitting the E key.

In my case, I edited the “Title”, “Author”, “Tags”, “Publisher” and “Languages”:

Calibre

Calibre doesn’t modify the PDF files themselves so I will need to export the files to a custom directory. In Calibre nomenclature, this is “Saving”. Highlight all the titles you want to export and hit “S” twice. Why twice? No idea. Choose the directory.

You can now copy the exported PDF files to your phone, tablet, whatever without fear of the v16.0 version of the P&T Guide being rejected by Aldiko because the v15.4 version is already added.

Here are the IQ v16.0 SP3 manuals that I’ve ‘fixed’ to work with Aldiko. They are identical to the PDFs on sybooks with the exception of the PDF fields I mentioned previously.

No copyright infringement is intended. SAP/Sybase, please feel free to take these and host them.

IQ 16.0 SP3 – Programming – SAP, Inc_
IQ 16.0 SP3 – Quick Start_ Unix_Linux – SAP, Inc_
IQ 16.0 SP3 – Reference_ Building Blocks, Tables, and Procedures – SAP, Inc_
IQ 16.0 SP3 – Reference_ Statements and Options – SAP, Inc_
IQ 16.0 SP3 – Release Bulletin_ Linux – SAP, Inc_
IQ 16.0 SP3 – SAP Sybase IQ Error Messages – SAP, Inc_
IQ 16.0 SP3 – Unstructured Data Analytics – SAP, Inc_ IQ 16.0 SP3 – User-Defined Functions – SAP, Inc_
IQ 16.0 SP3 – Utility Guide – SAP, Inc_
IQ 16.0 SP3 – Administration_ Backup, Restore, and Data Recovery – SAP, Inc_
IQ 16.0 SP3 – Administration_ Globalization – SAP, Inc_
IQ 16.0 SP3 – Administration_ In-Memory Row-Level Versioning – SAP, Inc_
IQ 16.0 SP3 – Administration_ Load Management – SAP, Inc_
IQ 16.0 SP3 – Administration_ Multiplex – SAP, Inc_
IQ 16.0 SP3 – Administration_ Spatial Data – SAP, Inc_
IQ 16.0 SP3 – Administration_ User Management and Security – SAP, Inc_
IQ 16.0 SP3 – Guide to Licensed Options – SAP, Inc_
IQ 16.0 SP3 – Introduction to SAP Sybase IQ – SAP, Inc_
IQ 16.0 SP3 – Linux Installation and Configuration Guide – SAP, Inc_
IQ 16.0 SP3 – Migration_ Unix_Linux – SAP, Inc_
IQ 16.0 SP3 – New Features Summary – SAP, Inc_
IQ 16.0 SP3 – Performance and Tuning Guide – SAP, Inc_
SAP Control Center 3.3 – Release Bulletin – SAP, Inc_
SAP Control Center for SAP Sybase IQ 3.3 – SAP, Inc_
Unified Agent and Agent Management Console 2.0.2 – User’s Guide – SAP, Inc_

SAP Sybase SQL Anywhere 12.0.1 manuals fixed to work with tablet/phone PDF readers like Aldiko

$
0
0

Aldiko Book Reader Premium Full v2.2.3.apkMany PDF readers for smart phones (Android/iphone) and tablets manage the pdf files Calibre_Logobased solely on the Title and Author fields in the PDF file. While for this is fine for your average book, it is not all that helpful with manuals that tend to have abbreviated or no data in the title/author fields. In the case of the manuals for Sybase IQ, I’m unable to load the manuals for say v11.0 and v12.0.1 as they have the same Title/Author data.

How to fix? Easy. Go get Calibre. Drop the PDF files on to the running Calibre. Edit them by hitting the E key.

In my case, I edited the “Title”, “Author”, “Tags”, “Publisher” and “Languages”:

Calibre

Calibre doesn’t modify the PDF files themselves so I will need to export the files to a custom directory. In Calibre nomenclature, this is “Saving”. Highlight all the titles you want to export and hit “S” twice. Why twice? No idea. Choose the directory.

SQL Anywhere 12.0.1 (r) Server – Database Administration – SAP, Inc_

You can now copy the exported PDF files to your phone, tablet, whatever without fear of the v12.0.1 version of the P&T Guide being rejected by Aldiko because the v12.0 version is already added.

Here are the SQL Anywhere v12.0.1 manuals that I’ve ‘fixed’ to work with Aldiko. They are identical to the PDFs on sybooks with the exception of the PDF fields I mentioned previously.

No copyright infringement is intended. SAP/Sybase, please feel free to take these and host them.

SQL Anywhere 12.0.1 (r) Server – Programming – SAP, Inc_
SQL Anywhere 12.0.1 (r) Server – Spatial Data Support – SAP, Inc_
SQL Anywhere 12.0.1 (r) Server – SQL Reference – SAP, Inc_
SQL Anywhere 12.0.1 (r) Server – SQL Usage – SAP, Inc_
SQL Anywhere 12.0.1 – Changes and Upgrading – SAP, Inc_
SQL Anywhere 12.0.1 – Error Messages – SAP, Inc_
SQL Anywhere 12.0.1 – Introduction – SAP, Inc_
SQL Anywhere 12.0.1 – MobiLinkTM – Client Administration – SAP, Inc_
SQL Anywhere 12.0.1 – MobiLinkTM – Getting Started – SAP, Inc_
SQL Anywhere 12.0.1 – MobiLinkTM – Server Administration – SAP, Inc_
SQL Anywhere 12.0.1 – MobiLinkTM – Server-Initiated Synchronization – SAP, Inc_
SQL Anywhere 12.0.1 – QAnywhereTM – SAP, Inc_
SQL Anywhere 12.0.1 – Relay Server – SAP, Inc_
SQL Anywhere 12.0.1 – SQL RemoteTM – SAP, Inc_
SQL Anywhere 12.0.1 – UltraLite(r) – .NET Programming – SAP, Inc_
SQL Anywhere 12.0.1 – UltraLite(r) – C and C__ Programming – SAP, Inc_
SQL Anywhere 12.0.1 – UltraLite(r) – Database Management and Reference – SAP, Inc_
SQL Anywhere 12.0.1 – UltraLite(r) – Java Programming – SAP, Inc_
SQL Anywhere 12.0.1 – UltraLite(r) – M-Business Anywhere Programming (deprecated) – SAP, Inc_

Open Watcom C/C++ & FORTRAN manuals fixed to work with tablet/phone PDF readers like Aldiko

$
0
0

Aldiko Book Reader Premium Full v2.2.3.apkMany PDF readers for smart phones (Android/iphone) and tablets manage the pdf files Calibre_Logobased solely on the Title and Author fields in the PDF file. While for this is fine for your average book, it is not all that helpful with manuals that tend to have abbreviated or no data in the title/author fields. In the case of the manuals for OpenWatcom C/C++ and FORTRAN, I’m unable to load the manuals as they have the same Title/Author data (WATCOM GML).

How to fix? Easy. Go get Calibre. Drop the PDF files on to the running Calibre. Edit them by hitting the E key.

In my case, I edited the “Title”, “Author”, “Tags”, “Publisher” and “Languages”:

Calibre

Calibre doesn’t modify the PDF files themselves so I will need to export the files to a custom directory. In Calibre nomenclature, this is “Saving”. Highlight all the titles you want to export and hit “S” twice. Why twice? No idea. Choose the directory.

You can now copy the exported PDF files to your phone, tablet, whatever without fear of the manuals being rejected by Aldiko.

Here are the OpenWatcom 1.8 manuals that I’ve ‘fixed’ to work with Aldiko. They are identical to the PDFs at OpenWatcom with the exception of the PDF fields I mentioned previously.

Open Watcom 1.8 – Debugger User’s Guide
Open Watcom 1.8 – FORTRAN 77 Getting Started
Open Watcom 1.8 – FORTRAN 77 Graphics Library Reference
Open Watcom 1.8 – FORTRAN 77 Language Reference
Open Watcom 1.8 – FORTRAN 77 Programmer’s Guide
Open Watcom 1.8 – FORTRAN 77 Tools User’s Guide
Open Watcom 1.8 – FORTRAN 77 User’s Guide
Open Watcom 1.8 – Graphical Tools User’s Guide
Open Watcom 1.8 – Linker User’s Guide Open Watcom
Open Watcom 1.8 – Script_GML Tutorial and Reference Manual
Open Watcom 1.8 – VI Editor Reference and User’s Guide
Open Watcom 1.8 – C Language Reference
Open Watcom 1.8 – C Library Reference
Open Watcom 1.8 – C++ Class Library Reference
Open Watcom 1.8 – C/C++ Getting Started
Open Watcom 1.8 – C/C++ Programmer’s Guide
Open Watcom 1.8 – C/C++ Tools User’s Guide
Open Watcom 1.8 – C/C++ User’s Guide

SAP Sybase IQ: How to Restore Your Backups to Another system

$
0
0

SAP/Sybase’s documentationSybase SAP isn’t very clear for new IQ dbas and developers. Once such item is simply restoring an IQ database on to another system. Unlike ASE, you need to specify the new file locations if they are different than the source server.

Assumptions:

  1. IQ software has been installed
  2. The new dbfile locations are symbolic links to raw partitions OR the path exists but not the files
  3. You have a valid SYSAM license for the new IQ instance.
  4. The new IQ instance name is set (via -n instance)
  5. The old directory for the .db, .log and .mir exists (use a symbolic link if you wish)

Obtain dbspace file names with sp_iqfile:

select DBFileName, Path, DBFileSize from sp_iqfile();
DBFileName	Path	DBFileSize
'IQ_SYSTEM_MAIN'	'/dba/syb/old_iq/sybdev/IQ_MAIN/old_iqmain001.iq'	'32G'
'IQ_USER_MAIN_FILE_01'	'/dba/syb/old_iq/sybdev/IQ_USER_MAIN/old_iqusermain001.iq'	'1024G'
'IQ_SYSTEM_TEMP'	'/dba/syb/old_iq/sybdev/IQ_TEMP/old_iqtemp001.iqtmp'	'32G'
'IQ_SYSTEM_TEMP_002'	'/dba/syb/old_iq/sybdev/IQ_TEMP/old_iqtemp002.iqtmp'	'32G'

Create a restore.sql file renaming the DBFileName to the new locations:

restore database 'new_iq'
FROM '/dba/backup/sybbackup/old_iq.20140423100111.17760.IQfullbkp'
RENAME IQ_SYSTEM_MAIN TO '/dba/syb/new_iq/sybdev/IQ_MAIN/new_iqmain001.iq'
RENAME IQ_SYSTEM_TEMP TO '/dba/syb/new_iq/sybdev/IQ_TEMP/new_iqtemp001.iq'
RENAME IQ_SYSTEM_TEMP_002 TO '/dba/backup/sybbackup/new_iqtemp002.iq'
RENAME IQ_SYSTEM_MSG TO '/dba/syb/new_iq/instlog/new_iq.iqmsg'
RENAME IQ_USER_MAIN_FILE_01 TO '/dba/syb/new_iq/sybdev/IQ_USER_MAIN/new_iqusermain001.iq';

Stop the destination IQ instance if it is running and start the utility database:

stop_iq
Checking system ...

The following 1 server(s) are owned by 'sybdba'

## Owner          PID   Started  CPU Time  Additional Information
-- ---------  -------  --------  --------  ------------------------------------
1: sybdba       13909     Apr24  00:43:46  SVR:new_iq DB:new_iq PORT:58116
              /dba/syb/new_iq/sybase/IQ-16_0/bin64/iqsrv16 @/dba/syb/new_iq/sybdb/new_iq.cfg /dba/syb/new_iq/sybdb/new_iq.db -gn 65 -o /dba/syb/new_iq/sybase/IQ-16_0/logfiles/
${SYBASE}/IQ-16_0/bin64/start_iq -n utility_db -gu dba -c 48m -gc 20 -iqgovern 30 \
        -gd all -gl all -gm 10 -gp 4096 -ti 4400 -z -zr all -zo $SYBASE/IQ-16_0/logfiles/utility_db.out \
        -o $SYBASE/IQ-16_0/logfiles/utility_db.srvlog -iqmc 100 -iqtc 100 -x "tcpip{port=9000}"
Starting server utility_db on localhost at port 9000 (04/30 09:37:16)

Run Directory       : /dba/syb/new_iq/sybdb
Server Executable   : /dba/syb/new_iq/sybase/IQ-16_0/bin64/iqsrv16
Server Output Log   : /dba/syb/new_iq/instlog/utility_db.srvlog
Server Version      : 16.0.0.653/sp03 16.0.0/Linux 2.6.18-194.el5
Open Client Version : N/A
User Parameters     : '-n' 'utility_db' '-gu' 'dba' '-c' '48m' '-gc' '20' '-iqgovern' '30' '-gd' 'all' '-gl' 'all' '-gm' '10' '-gp' '4096' '-ti' '4400' '-z' '-zr' 'all' '-zo' '/dba/syb/new_iq/instlog/utility_db.out' '-o' '/dba/syb/new_iq/instlog/utility_db.srvlog' '-iqmc' '100' '-iqtc' '100' '-x' 'tcpip{port=9000}'
Default Parameters  : -gn 25
….

Remove the db, log and mir files:

rm instance.db instance.log instance.mir

Restore the full backup:

dbisql -c "uid=dba;pwd=sql;eng=utility_db;dbn=utility_db" -port 9000 -host $( hostname ) -nogui "restore.sql"

Restore the incremental backup(s):

dbisql -c "uid=dba;pwd=sql;eng=utility_db;dbn=utility_db" -port 9000 -host $( hostname ) -nogui "restore_incrementals.sql"

Stop the utility database:

stop_iq

Start the IQ server to ensure it comes up then shut it back down.

If the name of the server has changed (e.g. old_iq -> new_iq), then we need to update the log and mir files. First let’s find out where the log and mir files are currently set to in the db file:

dblog new_iq.db
SQL Anywhere Transaction Log Utility Version 16.0.0.653
"new_iq.db" is using log file "/dba/syb/old_iq/sybdb/old_iq.log"
"new_iq.db" is using log mirror file "/dba/syb/old_iq/sybdb/old_iq.mir"
Transaction log starting offset is 0702994164
Transaction log current relative offset is 0000397583

Set the log file to “new_iq.log”:

dblog -t new_iq.log new_iq.db
SQL Anywhere Transaction Log Utility Version 16.0.0.653
"new_iq.db" was using log file "/dba/syb/old_iq/sybdb/old_iq.log"
"new_iq.db" is using log mirror file "/dba/syb/old_iq/sybdb/old_iq.mir"
"new_iq.db" is now using log file "new_iq.log"
Transaction log starting offset is 0702994164
Transaction log current relative offset is 0000397625

We need to clear the mir file(s) before we can assign a new one:

dblog -r new_iq.db
SQL Anywhere Transaction Log Utility Version 16.0.0.653
"new_iq.db" is using log file "new_iq.log"
"new_iq.db" was using log mirror file "/dba/syb/old_iq/sybdb/im00.mir"
"new_iq.db" is now using no log mirror file
Transaction log starting offset is 0702994164
Transaction log current relative offset is 0000397625

Set the mir file:

dblog -m new_iq.mir new_iq.db
SQL Anywhere Transaction Log Utility Version 16.0.0.653
"new_iq.db" is using log file "new_iq.log"
"new_iq.db" was using no log mirror file
"new_iq.db" is now using log mirror file "new_iq.mir"
Transaction log starting offset is 0702994164
Transaction log current relative offset is 0000397625

Start your IQ instance.

SAP Sybase IQ: Easily Extracting and Importing Data With Your IQ Data Warehouse

$
0
0

SAP/Sybase’s documentationSybase SAP isn’t very clear for new IQ dbas and developers. Once such item is simply extracting data from the warehouse into files that can be loaded into another IQ system when load table from location simply isn’t available or isn’t practical.

Assumptions:

  1. Extraction of table data with the owner of ‘JF’. Replace with the schemas you desire.
  2. Exported data will go to the /dba/backup/sybbackup/bkp/export/data_export directory.
  3. We will use isql with the parameters to connect stored in the $ISQL environment variable.
  4. The max temporary table size is 1TB. Increase as needed.

The simplest method is to simply create a shell script per table to export:

#!/bin/env bash

if [[ ! -d data_export ]]; then
  mkdir data_export
fi

set -A TABLES

TABLES=$( echo "set nocount on
go
select convert(varchar(80), user_name(creator) + '.' + table_name) from systable where user_name(creator) in ('JF') and table_type = 'BASE'
go
exit" | $ISQL -h -b  | sed -e '/affected/d' -e '/---/d' -e '/^$/d' )

for table in ${TABLES}; do
  echo
  echo "Generating /dba/backup/sybbackup/bkp/export/data_export/${table}_export.sql"
  sql_file=/dba/backup/sybbackup/bkp/export/data_export/${table}_export.sql

  echo "set temporary option Temp_Extract_Name1 = '/dba/backup/sybbackup/bkp/export/data_export/${table}.data'
  set temporary option Temp_Extract_Name2 = ''
  set temporary option Temp_Extract_Binary = 'on'
  set temporary option Temp_Extract_Swap = 'off'
    set temporary option TEMP_EXTRACT_SIZE1 = 1073741824
go

  select * from ${table}
go

  set temporary option Temp_Extract_name1 = ''
go" > $sql_file
done

Now that we have the script files, let’s extract the data by running the shell scripts and compress each exported file with the gzip program. You can cancel the export at any time with ctrl-c and restart it after the last exported table:

for TABLE in *.sql; do 
  datafile=$( echo $TABLE | sed -e 's/_export.sql$/.data/' )
  echo $datafile
  gzipfile=${datafile}.gz

  if [ -f $gzipfile ]; then
    echo "$gzipfile already exists"
  else
    $ISQL -i $TABLE 2>&1 > $TABLE.out
    gzip -1 $datafile
  fi
done

Now that we have that data exported, imagine that you copied the files to another system. How do you import that data assuming that the tables have already been completed? Easy. We will create a set of import script files.

LOCAL_PATH=/dba/backup/sybbackup/bkp/import/data_import

for TABLE_gzip in *.gz; do 
  datafile=$( echo $TABLE_gzip | sed -e 's/.gz$//' )
  TABLE_FILE=$( echo $TABLE_gzip | sed -e 's/.data.gz$//' )
  TABLE_OWNER=$( echo $TABLE_FILE | cut -d . -f1 )
  TABLE=$( echo $TABLE_FILE | cut -d . -f2 | sed -e 's/_export$//' )

  if [ -f ${datafile}.done ]; then
    echo "${datafile} already processed"
  else
    # ===================================================================
    # Generate the load commend to load the file
    # ===================================================================
    echo "#!/bin/env bash" > ${TABLE_OWNER}.${TABLE}_import.sh
    echo ". /dba/code/syb/.setenv" >> ${TABLE_OWNER}.${TABLE}_import.sh
    echo "" >> ${TABLE_OWNER}.${TABLE}_import.sh
    echo "echo \"uncompressing $TABLE_gzip\"" >> ${TABLE_OWNER}.${TABLE}_import.sh
    echo "gzip -dc $TABLE_gzip > $datafile" >> ${TABLE_OWNER}.${TABLE}_import.sh
    echo "">> ${TABLE_OWNER}.${TABLE}_import.sh
    echo "echo \"importing ${TABLE_OWNER}.${TABLE}\"" >> ${TABLE_OWNER}.${TABLE}_import.sh
    echo '$ISQL -b < <EOF'>> ${TABLE_OWNER}.${TABLE}_import.sh
    echo "select 'Start datetime'=convert(char(25), getdate(), 119), 'TABLENAME=${TABLE_OWNER}.${TABLE}'">> ${TABLE_OWNER}.${TABLE}_import.sh
    echo "go">> ${TABLE_OWNER}.${TABLE}_import.sh
    echo " ">> ${TABLE_OWNER}.${TABLE}_import.sh
    echo "truncate table ${TABLE_OWNER}.${TABLE}">> ${TABLE_OWNER}.${TABLE}_import.sh
    echo "go">> ${TABLE_OWNER}.${TABLE}_import.sh
    echo "commit">> ${TABLE_OWNER}.${TABLE}_import.sh
    echo "go">> ${TABLE_OWNER}.${TABLE}_import.sh
    echo "SET TEMPORARY OPTION IDENTITY_INSERT = '${TABLE_OWNER}.${TABLE}'">> ${TABLE_OWNER}.${TABLE}_import.sh
    echo "go">> ${TABLE_OWNER}.${TABLE}_import.sh
    echo "load table ${TABLE_OWNER}.${TABLE}">> ${TABLE_OWNER}.${TABLE}_import.sh
    echo "( ">> ${TABLE_OWNER}.${TABLE}_import.sh
    ../gen_iq_col_list_w_null_byte.sh ip00 $TABLE_OWNER $TABLE | sed -e '/row affected/d;s/ *$//;/^$/d'>> ${TABLE_OWNER}.${TABLE}_import.sh
    echo ")">> ${TABLE_OWNER}.${TABLE}_import.sh
    echo "from '${LOCAL_PATH}/${datafile}'">> ${TABLE_OWNER}.${TABLE}_import.sh
    echo "escapes off format binary">> ${TABLE_OWNER}.${TABLE}_import.sh
    echo "go">> ${TABLE_OWNER}.${TABLE}_import.sh
    echo "commit">> ${TABLE_OWNER}.${TABLE}_import.sh
    echo "go">> ${TABLE_OWNER}.${TABLE}_import.sh
    echo " ">> ${TABLE_OWNER}.${TABLE}_import.sh
    echo "select 'Start datetime'=convert(char(25), getdate(), 119), 'TABLENAME=${TABLE_OWNER}.${TABLE}'">> ${TABLE_OWNER}.${TABLE}_import.sh
    echo "go">> ${TABLE_OWNER}.${TABLE}_import.sh
    echo "SET TEMPORARY OPTION IDENTITY_INSERT = ''">> ${TABLE_OWNER}.${TABLE}_import.sh
    echo "go">> ${TABLE_OWNER}.${TABLE}_import.sh
    echo " ">> ${TABLE_OWNER}.${TABLE}_import.sh
    echo "EOF">> ${TABLE_OWNER}.${TABLE}_import.sh
    echo "" >> ${TABLE_OWNER}.${TABLE}_import.sh
    echo "rm -f $datafile">> ${TABLE_OWNER}.${TABLE}_import.sh
    echo " ">> ${TABLE_OWNER}.${TABLE}_import.sh
    chmod u+x ${TABLE_OWNER}.${TABLE}_import.sh
  fi
done

If the target system is a different endian (Linux x86-64 -> AIX), replace

echo "escapes off format binary">> ${TABLE_OWNER}.${TABLE}_import.sh

with

echo "escapes off format binary byte order high">> ${TABLE_OWNER}.${TABLE}_import.sh

We simply need to run each import script file:

for import_file in *_import.ksh ; do ./$import_file 2>&1 |tee  ${j}.out ; done

SAP Sybase ASE Unable to shutdown with there are not enough ‘user connections’ Error: 1601, Severity: 17, State: 3

$
0
0

If you’re trying to shutdown ASE and you’re not able to log in to the ASE instance, you can shutdown the instance with “kill -15 ” on Linux/Unix:

server  Error: 1601, Severity: 17, State: 3
server  There are not enough 'user connections' available to start a new process. Retry when there are fewer active users, or ask your System Administrator to reconfigure ASE with more user connections

Obtain the os PID simply by running showserver:

$ showserver
USER          PID %CPU %MEM   SZ  RSS    TTY STAT    STIME  TIME COMMAND
sybase    542123 15.1  1.0 52220 93356  pts/2 A    11:15:35  8:34 /sybase/ASE-15_0/bin/dataserver -d/dev/rmasterd001 -e/sybase/ASE-15_0/install/errorlog -c/sybase/ASE-15_0/sybase.cfg -isybase -ssybase -M/sybase/mem 

Kill the dataserver process with “kill -15″ triggering a “shutdown with nowait” within ASE:

$ kill -15 542123

Only as a last resort, use “kill -9″.

  • If you need to, verify with “ipcs -m” that the shared memory segments are released, if not use “ipcrm” to release it.
  • Verify with “netstat -an |grep ” that the bound port(s) that ASE uses are released. If not, you may need to restart the machine to release them.

SOLVED: SAP Sybase IQ SQL Anywhere error -203 Cannot set a temporary option for user (Rapid SQL)

$
0
0

Thanks to Joseph Weaver for supplying this workaround!
In Embarcadero’s Rapid SQL acceRapidSQLssing data within SAP IQ can sometimes result in a “SQL Anywhere Error -203: Cannot set a temporary option for user ‘XXXXXX’” error.  This is not an IQ issue.  

IQ-203-1

The Rapid SQL configuration needs to be updated by disabling the “Enable SET Query Options” by default:

IQ-203-2

You will need to restart Rapid SQL for the change to take effect.

Drew Montgomery’s sp__dbsubspace for SAP Sybase ASE space usage

$
0
0

A few years back we were both working at a company that needed a method to obtain Sybase ASE database space usage every few minutes. The output of Ed Barlow’s sp__dbspace was fine but it was an expensive call. Drew Montgomery devised a set of stored procedures that would partially cache the results. Kudos to Drew!

With large databases, several of the calculations would overflow. I’m made only minor changes, mainly convert(numeric(19,5), … ) inside the sum()s.

sp__dbsubspace output:


1> sp__dbsubspace
2> go
 Name         Data MB       Used MB        Percent Log MB    Log Used  Log Pct Total MB
 ------------ ------------- -------------- ------- --------- --------- ------- ---------------
 mydb               4836323      4134753.0   85.49     87079  48793.15   56.03         4923402
(return status = 0)

sp_dbsubspace code:

/************************************************************************************************************************************************
 *  This process will use a persistant table called sysdbspaceinfo.  It is not a previously defined sybase system table, but  
 *  is used by the sp__dbsubspace procedure.  The database that this table resides in is defined by the "sybsystemdb" 
 *  marker.  Please replace the "sybsystemdb" marker with an actual database prior to installing this procedure.  In some    
 *  cases you may want to use something like sybsystemprocs or sybsystemdb.  You may also use tempdb, but if you do
 *  you may want to define the table in the model database as well, so it will exist when the server is restarted.  Good luck
 *  and enjoy.                                                                        Drew Montgomery
 ************************************************************************************************************************************************/

use master
go

/*  This is to set the Truncate Log on Checkpoint option for the database with the space check table on, so it doesn't fill up.
 *     This was done in case the database being used for this doesn't have its logs regularly cleaned (some sybase system
 *     databases are like that).  If the database you are going to use has a regular log cleanup procedure, you may comment 
 *     out this section.                         DM                                                                                                                       */
sp_dboption sybsystemdb, "trunc. log", true
go

use sybsystemdb
go

checkpoint
go

/* Drops the table if it already exists, as a precaution for the create */
if object_id('sysdbspaceinfo') is not null  
 drop table sysdbspaceinfo
go

create table sysdbspaceinfo 
   (dbid int, 
    DataPages numeric(19,5), 
    DataPagesUsed numeric(19,5), 
    LogPages numeric(19,5),
    LogPagesUsed numeric(19,5), 
    LogFirstPage int,
    NumberOfObjects int    )
go

/* Unique index is required for the isolation level, and makes the access faster! */
create unique index UCsysdbspaceinfo on sysdbspaceinfo(dbid)
go

/* Go to the sybsystemprocs to install the procedure */
use sybsystemprocs
go

/* Drop it first, as a precaution */
if object_id("sp__dbsubspace") is not null
  drop procedure sp__dbsubspace
go

create procedure sp__dbsubspace 
          @dont_format char(1) = NULL,          /* Flag for indicating the need to have more or less formatted information */
          @LogThreshold float = 0.01,              /* Change threshold for the amount of log "movement" before a recalculation of the data space is performed.
                                                                   The default value of 0.01 represents a 1.0% change in the amont of log space or the first page pointer of the log.
                                                                   Please note: it is theoretically possible that the log pointer could move just less than this amount and have 
                                                                   an amount of log space used that is just less than this amount, therefore it is POSSIBLE that change could be 
                                                                   two times this amount before a recalculation of the data space is performend.  Possible but not very likely.        */
           @Force varchar(10) = NULL
                                                                    
as
/* ------------------------------------------------------------------------------------------------------------------------------------------------------------------------
 *  This procedure conceived and written by Drew Montgomery - please forward any and all substantial updates to 
 *        drew_montgomery@ameritech.net (so I can make this procedure better).  Thank you.                               
 * ------------------------------------------------------------------------------------------------------------------------------------------------------------------------*/

set nocount on
set lock nowait
set transaction isolation level 0

/* Declaration Section */
declare     @MixedFlag char,                                 /* Flag to signify if log and data are on the same device */
                @DataPages numeric(19,5),                  /* Number of data pages defined from sysusages */
                @LogPages numeric(19,5),                    /* Number of log pages defined from sysusages */
                @TotalPages numeric(19,5),                    /* Number of pages defined from sysusages */
                @DataPagesUsed numeric(19,5),           /* Number of data pages currently in use (reserved) */
                @LogPagesUsed numeric(19,5),             /* Number of log pages currently in use */
                @LogFirstPage bigint,                                /* First defined page of the transaction log */
                @NumberOfObjects int,                       /* for determining if a table has been dropped or added */
                @OldDataPages numeric(19,5),              /* Previous number of data pages defined from sysusages */
                @OldLogPages numeric(19,5),                /* Previous number of log pages defined from sysusages */
                @OldLogPagesUsed numeric(19,5),        /* Previous number of data pages being used */
                @OldDataPagesUsed numeric(19,5),       /* Previous number of log pages being used */
                @OldLogFirstPage int,                            /* Previous transaction log first page pointer */
                @OldNumberOfObjects int,                  /* Previous number of user tables in this database */
--                @LogDelta numeric(19,5),                       /* Change in the number of log pages being used */
--                @LFPDelta int,                                       /* Change in the location of the first log page */
                @scale numeric(19,5),                            /*  Multiplier used for displaying amount of space from number of pages -
                                                                                 this value is derived from the @@maxpagesize */
                @ReSize char,                                       /* Flag indicating if we need to recalculate the amount of data space being used */
                @pct_used numeric(10,2),                       /* Calculated percentage of data space used */
                @log_pct_used numeric(10,2)                  /* Calculated percentage of log space used */

set @ReSize = 'F'            /* Predefined as "No, thanks, we don't need to get a new reading of the data space being used -
                                          the old value will do just fine.   */

/* Determine the current data and log space allocated to this dabase as defined from sysusages */
select @DataPages = sum(case when segmap=4 then 0 else convert(numeric(19,5), size) end),
          @LogPages = sum(case when segmap & 4=4 then convert(numeric(19,5), size) else 0 end),
          @TotalPages = sum(convert(numeric(19,5), size))
  from master..sysusages where dbid = db_id()

/* If there are no log pages (or the value is null), then the system is defined as having Mixed data and log space -
 *   which also means that the number of potential log pages is the same as the number of data pages.              */
if isnull(@LogPages,0) = 0
begin
  set @MixedFlag = 'M'  -- Mode is Mixed
  set @LogPages=@DataPages
end
else if exists (select 1 from master..sysusages where dbid = db_id() and segmap &5 =5)
  set @MixedFlag = "C"  -- Stands for Confused
else
  set @MixedFlag = 'P'  -- Indicates Pristine

/* We are getting the number of pages being used by the syslogs table (table id = 8).
 * The first select line is "Prior to system 15 version", the second is the "System 15 or above" version-
 *   Please set the appropriate comment as to which kind of system is being used */
/*  select @LogPagesUsed = reserved_pgs(id, doampg), */
select @LogPagesUsed = reserved_pages(db_id(), id), 
          @LogFirstPage = first
  from sysindexes
 where id = 8

/* Extract the information from previous executions of sp__dbsubspace */
select @OldDataPages = DataPages, 
          @OldDataPagesUsed = DataPagesUsed,
          @OldLogPages = LogPages,
          @OldLogPagesUsed = LogPagesUsed,
          @OldLogFirstPage = LogFirstPage,
          @OldNumberOfObjects = NumberOfObjects
  from sybsystemdb..sysdbspaceinfo
where dbid = db_id()

/* Get an object count of the USER TABLES */
select @NumberOfObjects = count(*) from sysobjects where type = 'U'

/* If there are no records retrieved (first run) we need to Recalculate the size */
if @@rowcount = 0
begin
  set @ReSize = 'T'
end
else        
  if @OldDataPages != @DataPages           /* If the number of data pages changed from sysusages - Recalculate size */
  begin
    set @ReSize = 'T'
  end
  else
    if @OldLogPages != @LogPages            /* If the nubmer of log pages changed from sysusages - Recalculate size */
    begin
      set @ReSize = 'T'
    end
    else
    begin                                                   /* if the number of log pages used is greather than a percentage of the total number of log pages available - Recalc Size */
      if (@LogPagesUsed - @OldLogPagesUsed) > @LogThreshold * @LogPages
        set @ReSize = 'T'
      else
        begin                                               /* if the log's first page moved more than the threshold of the number of log pages available - Recalc Size */
        if (abs(@LogFirstPage - @OldLogFirstPage)) > @LogThreshold * @LogPages
          set @ReSize = 'T'
        else
          begin
            if (@OldNumberOfObjects != @NumberOfObjects)
              set @ReSize = 'T'
          end
        end
    end

if @Force is not null  -- This is a force option to make it update the value
  set @ReSize = 'T'

if @ReSize = 'T'                                        /* We are recalculating size, and getting back the new value of the Data Pages Used */
  exec sp__dbsubspace;2 @DataPages, @DataPagesUsed out, @LogPages, @LogPagesUsed, @LogFirstPage, @NumberOfObjects
else
begin                                                       /* or if we don't need to do that, we just use the previous value of the Data Pages Used */
  set @DataPagesUsed = @OldDataPagesUsed
end

/* Calculated scale from the maximum page size (size of the data pages, usually 2k, 4k, 8k, or 16k) */
set @scale = @@maxpagesize / 1024

/* "Borrowed" this calculation from sp__dbspace of the percentages used*/
if @MixedFlag = 'M' 
begin  /* Please note, if the mode is mixed, we will apparently have no Log Percentage Used as it is part of the data space */
  set @pct_used = convert(numeric(10,2), ((@DataPagesUsed + @LogPagesUsed) * 100) / @DataPages)
  set @log_pct_used = convert(numeric(10,2), 0)
end
else
begin
  set @pct_used = convert(numeric(10,2), (@DataPagesUsed * 100) / @DataPages) 
  set @log_pct_used = convert(numeric(10,2), (@LogPagesUsed * 100 )/(@LogPages) ) 
end

/* The @dont_format is from the sp__dbspace command - and provides the option for an abbreviated display of information */
if @dont_format is not null
begin            /* Provide the results based on the local variables - formatted first */
select  Name             = db_name(),
        "Data MB"  = str((@DataPages*@scale)/1024, 16, 0),
        "Used MB"  = str(((@DataPagesUsed + case @MixedFlag when 'M' then @LogPagesUsed else 0 end)*@scale)/1024, 16, 1),
        Percent    = str(@pct_used, 7, 2),
        "Log MB" = str((@LogPages*@scale)/1024, 12, 0),
        "Log Used"   = str(((case @MixedFlag when 'M' then 0 else @LogPagesUsed end)*@scale)/1024, 12, 2),
        "Log Pct"  = str(@log_pct_used, 7, 2),
        "Total MB" = str((@TotalPages*@scale)/1024, 18, 0)
end
else
begin          /* And unformatted */
select  Name             = convert(char(12),db_name()),
        "Data MB"  = str((@DataPages*@scale)/1024, 13, 0),
        "Used MB"  = str(((@DataPagesUsed + case when @MixedFlag = 'M' then @LogPagesUsed else 0 end)*@scale)/1024, 14, 1),
        Percent    = str(@pct_used, 7, 2),
        "Log MB"   = str((@LogPages*@scale)/1024, 9, 0),
       "Log Used" = str(((case when @MixedFlag='M' then 0 else @LogPagesUsed end)*@scale)/1024, 9, 2),
        "Log Pct"  = str(@log_pct_used, 7, 2),
        "Total MB" = str((@TotalPages*@scale)/1024, 15, 0)
end

/*  And Vola' we are done!  */
go

/* This is a subordinate procedure that gets the information from the sysindexes (or sysobjects for system 15+) and stores the information into the sysdbspaceinfo table */
create procedure sp__dbsubspace;2
  @DataPages numeric(19,5),                           /* See comments above about variables */
  @DataPagesUsed numeric(19,5) output,         /* NOTE: this value is returned to the calling procedure */
  @LogPages numeric(19,5),
  @LogPagesUsed numeric(19,5),
  @LogFirstPage bigint,
  @NumberOfObjects int

with recompile
as

  /* Prior to system 15 version */
  /* select @DataPagesUsed = sum(reserved_pgs(id, doampg) + reserved_pgs(id, ioampg))
     from sysindexes
    where id != 8
  */
/* System 15 and above version */    
   select @DataPagesUsed = sum(convert(numeric(19,5), reserved_pages(db_id(), id)))
     from sysobjects
    where id != 8
    
    
 /* Update the information in the table */
      update sybsystemdb..sysdbspaceinfo 
           set  DataPages = @DataPages,
                 DataPagesUsed = @DataPagesUsed,
                 LogPages = @LogPages,
                 LogPagesUsed = @LogPagesUsed,
                 LogFirstPage = @LogFirstPage,
                 NumberOfObjects = @NumberOfObjects
         where dbid = db_id()                 

/* if the update is not for any rows, then add a row */
        if @@rowcount = 0
          insert into sybsystemdb..sysdbspaceinfo values (db_id(), @DataPages, @DataPagesUsed, @LogPages, @LogPagesUsed, @LogFirstPage, @NumberOfObjects)
          
return  /* and we are done with this one */
go

/* You may want to grant some permissions (execute, perhaps) if the users are not sa's */

A fast method of getting space utilization: sp__quickdbspace for SAP Sybase ASE

$
0
0

The sp__quickdbspace procedure relies on accurate metrics provided by free space accounting and/or dbcc checkalloc/tablealloc. It shouldn’t be relied upon on for exact space usage.

Much of the code comes from sp_helpdb from Sybase. er.. SAP.

sp__quickdbspace output:


1>  sp__quickdbspace mydb
2> go
 DBName               data size MB       data free MB       log free MB
 -------------------- ------------------ ------------------ ------------------
 mydb                         5025662.00          703975.00          186260.00
(return status = 0)
1>

sp__quickdbspace code:

if exists (select 1 from sysobjects where name = "sp__quickdbspace")
  drop procedure sp__quickdbspace
go

create procedure sp__quickdbspace 
@dbname varchar(255) = NULL
as
declare @numpgsmb float	/* Number of Pages per Megabyte */
declare @sptlang int
declare @log_free bigint

set nocount on

if @dbname = null
  select @dbname = db_name()

select @numpgsmb = (1048576. / v.low)
from master.dbo.spt_values v
where v.number = 1
and v.type = "E"	

select @sptlang = @@langid

if @@langid != 0
begin
  if not exists (select * from master.dbo.sysmessages where error between 17050 and 17069 and langid = @@langid)
    select @sptlang = 0
  else
    if not exists (select * from master.dbo.sysmessages where error between 17110 and 17119 and langid = @@langid)
      select @sptlang = 0
end

select 
  device_fragments = v.name,
  size = (size / @numpgsmb),
  usage = convert(char(30), m.description),
  created = convert(char(25), u.crdate, 100),
  case
    when u.segmap = 4 then null
    else (convert(bigint, curunreservedpgs(d.dbid, u.lstart, u.unreservedpgs)) / @numpgsmb)
  end "free_mb"
  into #device_usage
from master.dbo.sysdatabases d,
  master.dbo.sysusages u,
  master.dbo.sysdevices v,
  master.dbo.spt_values b,
  master.dbo.sysmessages m
where d.dbid = u.dbid
  and u.vdevno = v.vdevno
  and ((v.status & 2 = 2)  or (v.status2 & 8 = 8))
  and d.name = @dbname
  and b.type = 'S'
  and u.segmap & 7 = b.number
  and b.msgnum = m.error
  and isnull(m.langid, 0) = @sptlang
  
	if exists (select *
	    from master.dbo.sysdatabases d, master.dbo.sysusages u
		where d.name like @dbname
			and d.dbid = u.dbid
			and u.segmap = 4
			and (d.status & ( 32 + 64 + 128 + 256) = 0)
			and (d.status2 & 64) = 0)
	begin
		 select @log_free = (lct_admin("logsegment_freepages", db_id(@dbname) ) - lct_admin("reserved_for_rollbacks", db_id(@dbname))) / @numpgsmb
	end
    
    select convert(varchar(20), @dbname) as "DBName", convert(numeric(15,2), sum(size)) as "data size MB", convert(numeric(15,2), sum(free_mb)) as "data free MB", convert(numeric(15,2), @log_free) as "log free MB" from #device_usage
    
drop table #device_usage
go

SAP Sybase IQ: Index Advisor for a user

$
0
0

There are times when you need individual users the ability to determine what indexes are suggested by the index advisor but you don’t want or are unable to give them full dba access. All you need to do is grant the execute permission on the sp_iqindexadvice stored procedure.

Grant execute on sp_iqindexadvice to <user>;

create table test (col1 int, col2 varchar(10));
insert into test values (1, 'test1');
insert into test values (2, 'test2');
insert into test values (3, 'test3');
insert into test values (4, 'test4');
commit;

SET OPTION index_advisor = 'ON';
SET OPTION index_advisor_max_rows = 100;
commit;

select * from test where col1 =1 ;
commit;

call sp_iqindexadvice ();</user>

SAP ASE: Using unix domain sockets for turbo bulk copying (BCP)

$
0
0

Cory Sane back in March SAP Sybase2013 on SCN wrote about using unix domain sockets for bulk copying of data in/out of SAP Sybase ASE 15.7.

If you don’t know what unix domain sockets are, Thomas Stover over at Tech Deviancy wrote up an excellent Demystifying Unix Domain Sockets post. Highly recommended!
As usual, Wikipedia also has an article.

What is so great about unix domain sockets? You bypass the networking layer completely. This translates into faster communication between bcp (or similar) and ASE. The downside? The bcp file(s) must be on the same host as the ASE instance and your user must have read/write access to the ‘file’.

Using unix domain sockets with a 16k packet size appears to be ideal for the bcp out (1 million rows in the test). Notice the difference of time between using normal (tcp) connection of 5K rows / second compared to 104k rows / second connecting with unix domain socket.

Unix Domain Sockets

tcp - packet size 65024
test #1  : Clock Time (ms.): total = 184821  Avg = 0 (5410.64 rows per sec.)
test #2  : Clock Time (ms.): total = 178612  Avg = 0 (5598.73 rows per sec.)

uds - packet size 2048
test #3  : Clock Time (ms.): total = 10843  Avg = 0 (92225.40 rows per sec.)
test #4  : Clock Time (ms.): total = 11012  Avg = 0 (90810.03 rows per sec.)

uds - packet size 8192
test #5  : Clock Time (ms.): total = 9823  Avg = 0 (101801.89 rows per sec.)
test #6  : Clock Time (ms.): total = 9965  Avg = 0 (100351.23 rows per sec.)

uds - packet size 12288
test #7  : Clock Time (ms.): total = 9735  Avg = 0 (102722.14 rows per sec.)
test #8  : Clock Time (ms.): total = 9745  Avg = 0 (102616.73 rows per sec.)

uds - packet size 16384
test #9  : Clock Time (ms.): total = 9587  Avg = 0 (104307.92 rows per sec.)
test #10 : Clock Time (ms.): total = 9558  Avg = 0 (104624.40 rows per sec.)

uds - packet size 32768
test #11 : Clock Time (ms.): total = 13205  Avg = 0 (75728.89 rows per sec.)
test #12 : Clock Time (ms.): total = 12961  Avg = 0 (77154.54 rows per sec.)

uds - packet size 65024
test #13 : Clock Time (ms.): total = 13254  Avg = 0 (75448.92 rows per sec.)
test #14 : Clock Time (ms.): total = 13179  Avg = 0 (75878.29 rows per sec.)

With unix domain sockets, we come close to DTU speeds without the penalty of exclusive table locks and a DTU process you can’t kill. It really is like pushing the turbo button!

Obviously, if you are bulk copying out of a view that uses a monster index you you may not see a huge difference, if any, because the majority of the time will transverse that index.

You will see a larger boost with bulk copying out of data than in of data. Why? The network layer is usually not the bottleneck when inserting of data. The bottleneck tends to be more allocating/populating pages in the database or index population if you haven’t dropped the indexes. YMMV

Setting up unix domain sockets is very simple and does NOT require a reboot. Let’s me show you how:

The format of the query master lines you would add to the interfaces file is simple:

query afunix unused //hostname/directory_you_can_write_to/file_name
master afunix unused //hostname/directory_you_can_write_to/file_name

for example:

query afunix unused //myase/dbms/sybase/ASE.socket
master afunix unused //myase/dbms/sybase/ASE.socket

If you want to start the listener without restarting, use sp_listener:

sp_listener 'start', 'afunix://hostname:/directory_you_can_write_to/file_name'

for example:

sp_listener 'start', 'afunix://myase:/dbms/sybase/ASE.socket'

SAP Sybase IQ Data Warehouse Index Advisor and awk

$
0
0

If you are running SAP’s IQ Data Warehouse SAP_IQsomewhere in your organization, there will be a time when you need to enable the Index Advisor (see SAP Sybase IQ: Index Advisor for a user) and parse the output. One problem is that the output will go to the IQ message log (IQ.iqmsg) which is already polluted with other information. So how can you easily pull out the recommendations and still keep your sanity?

A little AWK will do the majority of the work for you:

 awk 'BEGIN {COLSTART=6;COLEND=17}/Add |Rebuild /{ for (i=COLSTART;i< =COLEND;i++) printf("%s%s",$(i), i<COLEND ? OFS :"\n"); }' IQ.iqmsg | sort | uniq -c | sort -n |tail -10

produces the following “top 10″ index advisories:

 8 Add a unique HG index to join key column SCHEMA_B.STUFF_SKILL_SYSTEM.STUFF_SKILL_ID
 8 Add unique LF index on SCHEMA_A.STUFF_SKILL_SYSTEM.STUFF_SKILL_ID
 9 Add a unique HG index to join key column SCHEMA_A.STUFF_SYSTEM.STUFF_ID
12 Add a HG index to join key column SCHEMA_B.STUFF_SYSTEM.SOURCE_STUFF_ID
12 Add a unique HG index to join key column SCHEMA_B.STUFF_SKILL_ID_MAP.TYPE_ID
12 Condition 1 Index Advisor: Add LF index on SCHEMA_B.STORAGE_SYSTEM.SYSTEM_ID
22 Condition 2 Index Advisor: Add LF index on SCHEMA_B.STORAGE_SYSTEM.STATUS_C
32 Add LF index on SCHEMA_A.MOON_TREE.MOON_TREE_CONTEXT_ID
34 Add unique LF index on SCHEMA_A.STUFF_OBTUSE_CALLER_MAP.STUFF_CALLER_OBTUSE_ID
34 Add unique LF index on SCHEMA_A.STUFF_OBTUSE_MAP.STUFF_OBTUSE_ID

That AWK code looks pretty ugly doesn’t it? Well, it is simpler than you think.

BEGIN {
    COLSTART=6;
    COLEND=17
}
/Add |Rebuild /{
    for (i=COLSTART; i< =COLEND; i++) 
        printf("%s%s",$(i), i<COLEND ? OFS :"\n"); 
}

The BEGIN block runs before any data is parsed. We need to print columns 6 to 17 for each line that matches. We set the COLSTART (starting column) to 6 and COLEND (ending column) to be 17.

/Add |Rebuild /

Simply means if the line contains “Add ” or “Rebuild ” then do whatever is in the code block (between the curly braces).

for (i=COLSTART; i< =COLEND; i++)

For each number between 6 and 17 execute the following line.

printf("%s%s",$(i), i<colend ? OFS :"\n");

Print the column and the field separator. If we’re looking at column 17, then we print the column and a new line.

Next we sort the output of awk: sort

Now that we have sorted output, we count any duplicate index recommendations, print the # of duplicates and the unique line

Let’s sort on the number of duplicate index recommendations with sort -n

In this case, we only want the top 10 index recommendations: tail -10

This is based on the recommendation from SAP consultant Steve Bologna:

egrep -i "Add " IQ.iqmsg | awk '{ print $6 " " $7 " " $8 " " $9 " " $10 " " $11 " " $12 " " $13 " " $14 " " $15 " " $16 " " $17 }' | sort | uniq -c | sort -n

HOWTO: SAP Sybase IQ / SQL Anywhere : searching date, datetime, time fields

$
0
0

If you’re new to IQ (or SQL Anywhere) you may run into an oddity that if you connect with ISQL the following code works but doesn’t work in DBISQL:

SELECT col1_date
FROM mytable
WHERE col1_date >= '06/01/2014'

This is because any connection to IQ using the native connection (SQL Anywhere connection) that is used by dbisql and the like expects string to datetime format of “YYYY-MM-DD HH:NN:SS.SSS”. This is not changeable by setting an option. The string needs to be converted using a style (datetime string style # 103) prior to being used as a SARG.

SELECT col1_date
FROM mytable
WHERE col1_date >= convert(datetime, '06/01/2014', 103)

Even those of us that have been around for eons tend to forget ‘little’ gotchas like this.

From http://infocenter.sybase.com/help/index.jsp?topic=/com.sybase.infocenter.dc36271.1570/html/blocks/X41864.htm :

Table 2-3: Date format conversions using the style parameter
Without century (yy) With century (yyyy) Standard Output
Key “mon” indicates a month spelled out, “mm” the month number or minutes. “HH ”indicates a 24-hour clock value, “hh” a 12-hour clock value. The last row, 23, includes a literal “T” to separate the date and time portions of the format.
- 0 or 100 Default mon dd yyyy hh:mm AM (or PM)
1 101 USA mm/dd/yy
2 2 SQL standard yy.mm.dd
3 103 English/French dd/mm/yy
4 104 German dd.mm.yy
5 105 dd-mm-yy
6 106 dd mon yy
7 107 mon dd, yy
8 108 HH:mm:ss
- 9 or 109 Default + milliseconds mon dd yyyy hh:mm:ss AM (or PM)
10 110 USA mm-dd-yy
11 111 Japan yy/mm/dd
12 112 ISO yymmdd
13 113 yy/dd/mm
14 114 mm/yy/dd
14 114 hh:mi:ss:mmmAM(or PM)
15 115 dd/yy/mm
- 16 or 116 mon dd yyyy HH:mm:ss
17 117 hh:mmAM
18 118 HH:mm
19 hh:mm:ss:zzzAM
20 hh:mm:ss:zzz
21 yy/mm/dd HH:mm:ss
22 yy/mm/dd HH:mm AM (or PM)
23 yyyy-mm-ddTHH:mm:ss

The default values (style 0 or 100), and style 9 or 109 return the century (yyyy). When converting to char or varchar from smalldatetime, styles that include seconds or milliseconds show zeros in those positions.


Ed Barlow Stored Procedures: sp__monunusedindex updated with formatting, including owner and all indexes for SAP Sybase ASE 15 and higher

$
0
0

Ed Barlow createdSAP Sybase the sp__monunusedindex stored procedure for displaying the indexes that have not been used since server start in Sybase ASE as part of the excellent Extended Stored Procedures by Ed Barlow (AKA the Ed Barlow Stored Procedures).

I’ve updated the stored procedure to include the table owner and all the indexes & index keys. I’ve also fixed the formatting of the data.

$ diff sp__monunusedindex.old sp__monunusedindex.15
21a22,27
> --------------------------------------------------------------------------------------------------
> -- Vers|   Date   |      Who           | DA | Description
> -------+----------+--------------------+----+-----------------------------------------------------
> -- 1.1 |11/20/2013|  Jason Froebe      |    | Show full index name and full index keys
> -- 1.0 |  2006    |  Edward Barlow     |    | show indexes that have not been used since server start
> -------+----------+--------------------+----+-----------------------------------------------------
23c29,34
< select Dbname=db_name(DBID),Object=object_name(ObjectID,DBID),IndexID,IndexName=i.name, ObjectID
---
>
> declare @max_ownername_size varchar(3)
> declare @max_keylist_size varchar(4)
> declare @exec_str varchar(2000)
>
> select Dbname=db_name(DBID), Object=object_name(ObjectID,DBID), IndexID, IndexName=i.name, ObjectID
27,39c38,45
< and   a.ObjectID=o.id  and DBID=db_id()
< and   o.id = i.id and a.IndexID=i.indid
< and   o.type='U'
< and       (LastOptSelectDate is null and OptSelectCount=0)
< -- and   RowsUpdated=0
< -- and   RowsDeleted=0
< -- and   PhysicalReads=0
< -- and   PhysicalWrites=0
< -- and   PagesRead=0
< and   object_name(ObjectID,DBID) not like 'sys%'
< and   object_name(ObjectID,DBID) not like 'rs_%'
< and    object_name(ObjectID,DBID) not like 'spt_%'
< and   IndexID!=0
---
>    and   a.ObjectID=o.id  and DBID=db_id()
>    and   o.id = i.id and a.IndexID=i.indid
>    and   o.type='U'
>    and       (LastOptSelectDate is null and OptSelectCount=0)
>    and   object_name(ObjectID,DBID) not like 'sys%'
>    and   object_name(ObjectID,DBID) not like 'rs_%'
>    and    object_name(ObjectID,DBID) not like 'spt_%'
>    and        IndexID!=0
42,45c48,51
< owner      char(30) not null,
<    uid        smallint not null,
<    name       char(30) not null,
<    index_name char(30) not null,
---
>    owner      sysname not null,
>    uid        int not null,
>    name       longsysname not null,
>    index_name longsysname not null,
53c59
< keylist    char(127) null,
---
>    keylist    varchar(2000) null,
58,73c64,79
< insert into   #indexlist
<    select owner      = user_name(o.uid),
<           o.uid,
<           name       = o.name,
<           index_name = i.name,
<           id = i.id,
<           indexid    = i.indid,
<           clust      = convert(char(1),null),
<           allow_dup  = convert(char(1),null),
<           ign_dup_key  = convert(char(1),null),
<           uniq       = convert(char(1),null),
<           suspect    = convert(char(1),null),
<           keylist    = convert(char(127),"N.A."),
<           status      = status, status2=i.status2
<    from   sysobjects o, sysindexes i, #tmp t
<    where  i.id   = o.id
---
> insert into   #indexlist
> select owner      = user_name(o.uid),
>    o.uid,
>    name       = o.name,
>    index_name = i.name,
>    id = i.id,
>    indexid    = i.indid,
>    clust      = convert(char(1),null),
>    allow_dup  = convert(char(1),null),
>    ign_dup_key  = convert(char(1),null),
>    uniq       = convert(char(1),null),
>    suspect    = convert(char(1),null),
>    keylist    = "N.A.",
>    status      = status, status2=i.status2
> from   sysobjects o, sysindexes i, #tmp t
> where  i.id   = o.id
75d80
< --and    o.type in ("U",@show_type)
106c111
< or     status2&8192= 8192
---
>    or status2 & 8192= 8192
111c116
< while ( @count < 17 )   /* 16 appears to be the max number of indexes */
---
> while ( @count < 250 )   /* max number of indexes = 250 */
113d117
<
120c124
<       set    keylist=rtrim(keylist)+","+index_col(name,indexid,@count,uid)
---
>       set    keylist = convert(varchar(2000), rtrim(keylist)+", "+index_col(name,indexid,@count,uid))
123c127,128
< if @@rowcount=0   break
---
>    if @@rowcount=0
>       break
132,138c137,143
< if @no_print is null
<         begin
<         print "   INDEX KEY:     c = clustered            u = unique"
<         print "                  a = allow dup row        s = suspect"
<         print "                  i = ignore dup key "
<         print ""
<               end
---
> if @no_print is null
> begin
>    print "   INDEX KEY:     c = clustered            u = unique"
>    print "                  a = allow dup row        s = suspect"
>    print "                  i = ignore dup key "
>    print ""
> end
140,146c145,173
< select "Name" = rtrim(name)+"."+index_name,
<        c   = isnull(clust,""),
<        u   = isnull(uniq,""),
<        i   = isnull(ign_dup_key,""),
<        a   = isnull(allow_dup,""),
<        s   = isnull(suspect,""),
<        "List of Index Keys"    = keylist
---
> if @dont_format is null
> begin
>    select @max_ownername_size = convert(varchar(3), isnull(max(char_length(owner)) + max(char_length(name)) + max(char_length(index_name)) + 2, 1) )
>       from #indexlist
>
>    select @max_keylist_size = convert(varchar(4), isnull(max(char_length(keylist)), 1) )
>       from #indexlist
>
>    select @exec_str =
>       'select "Name" = convert(varchar(' + @max_ownername_size + '), rtrim(owner) + "." + rtrim(name) + "." + index_name),
>          c   = isnull(clust,""),
>          u   = isnull(uniq,""),
>          i   = isnull(ign_dup_key,""),
>          a   = isnull(allow_dup,""),
>          s   = isnull(suspect,""),
>          "List of Index Keys"    = convert(varchar(' + @max_keylist_size + '), keylist)
>       from #indexlist
>       order by owner,name,indexid'
>    exec (@exec_str)
> end
> else
> begin
>    select "Name" = rtrim(owner) + "." + rtrim(name) + "." + index_name,
>       c   = isnull(clust,""),
>       u   = isnull(uniq,""),
>       i   = isnull(ign_dup_key,""),
>       a   = isnull(allow_dup,""),
>       s   = isnull(suspect,""),
>       "List of Index Keys"    = keylist
148a176
> end

full code of sp__monunusedindex:

use sybsystemprocs
go
/* Procedure copyright(c) 2006 by Edward M Barlow */

/******************************************************************************
**
** Name        : sp__monunusedindex
**
** Created By  : Ed Barlow
**
******************************************************************************/

IF EXISTS (SELECT * FROM sysobjects
           WHERE  name = "sp__monunusedindex"
           AND    type = "P")
   DROP PROC sp__monunusedindex

go

create proc sp__monunusedindex( @dont_format char(1) = null, @no_print char(1) = null)
as
--------------------------------------------------------------------------------------------------
-- Vers|   Date   |      Who           | DA | Description
-------+----------+--------------------+----+-----------------------------------------------------
-- 1.1 |11/20/2013|  Jason Froebe      |    | Show full index name and full index keys
-- 1.0 |  2006    |  Edward Barlow     |    | show indexes that have not been used since server start
-------+----------+--------------------+----+-----------------------------------------------------
begin

declare @max_ownername_size varchar(3)
declare @max_keylist_size varchar(4)
declare @exec_str varchar(2000)

select Dbname=db_name(DBID), Object=object_name(ObjectID,DBID), IndexID, IndexName=i.name, ObjectID
into #tmp
from master..monOpenObjectActivity a, sysobjects o, sysindexes i
where RowsInserted=0
   and   a.ObjectID=o.id  and DBID=db_id()
   and   o.id = i.id and a.IndexID=i.indid
   and   o.type='U'
   and       (LastOptSelectDate is null and OptSelectCount=0)
   and   object_name(ObjectID,DBID) not like 'sys%'
   and   object_name(ObjectID,DBID) not like 'rs_%'
   and    object_name(ObjectID,DBID) not like 'spt_%'
   and  IndexID!=0

create table #indexlist (
   owner      sysname not null,
   uid        int not null,
   name       longsysname not null,
   index_name longsysname not null,
   id         int not null,
   indexid    smallint not null,
   clust      char(1) null,
   allow_dup  char(1) null,
   ign_dup_key char(1) null,
   uniq       char(1) null,
   suspect    char(1) null,
   keylist    varchar(2000) null,
   status     smallint not null,
   status2     smallint not null
)

insert into   #indexlist
select owner      = user_name(o.uid),
   o.uid,
   name       = o.name,
   index_name = i.name,
   id = i.id,
   indexid    = i.indid,
   clust      = convert(char(1),null),
   allow_dup  = convert(char(1),null),
   ign_dup_key  = convert(char(1),null),
   uniq       = convert(char(1),null),
   suspect    = convert(char(1),null),
   keylist    = "N.A.",
   status      = status, status2=i.status2
from   sysobjects o, sysindexes i, #tmp t
where  i.id   = o.id
   and    i.id = ObjectID and i.indid=IndexID
   and      indid > 0

/* delete multiple rows */
delete #indexlist
from   #indexlist a, #indexlist b
where  a.indexid = 0
and    b.indexid != 0
and    a.name = b.name

update #indexlist
set    clust='Y'
where  indexid = 1
or                      status&16=16
or              status2&512 = 512

update #indexlist
set    uniq = 'Y'
where  status & 2 = 2

update #indexlist
set    ign_dup_key = 'Y'
where  status & 1 = 1

update #indexlist
set    allow_dup = 'Y'
where  status & 64 = 64

update #indexlist
set    suspect = 'Y'
where  status & 32768 = 32768
   or status2 & 8192= 8192

declare @count int
select  @count=1

while ( @count < 250 )   /* max number of indexes = 250 */
begin
   if @count=1
      update #indexlist
      set    keylist=index_col(name,indexid,1,uid)
      where  index_col(name,indexid,@count,uid) is not null
   else
      update #indexlist
      set    keylist = convert(varchar(2000), rtrim(keylist)+", "+index_col(name,indexid,@count,uid))
      where  index_col(name,indexid,@count,uid) is not null

   if @@rowcount=0
      break

   select @count=@count+1
end

update #indexlist
set    name=convert(char(30), rtrim(rtrim(substring(owner,1,15)) + "." +name))
where  owner!="dbo"

if @no_print is null
begin
   print "   INDEX KEY:     c = clustered            u = unique"
   print "                  a = allow dup row        s = suspect"
   print "                  i = ignore dup key "
   print ""
end

if @dont_format is null
begin
   select @max_ownername_size = convert(varchar(3), isnull(max(char_length(owner)) + max(char_length(name)) + max(char_length(index_name)) + 2, 1) )
      from #indexlist

   select @max_keylist_size = convert(varchar(4), isnull(max(char_length(keylist)), 1) )
      from #indexlist

   select @exec_str =
      'select "Name" = convert(varchar(' + @max_ownername_size + '), rtrim(owner) + "." + rtrim(name) + "." + index_name),
         c   = isnull(clust,""),
         u   = isnull(uniq,""),
         i   = isnull(ign_dup_key,""),
         a   = isnull(allow_dup,""),
         s   = isnull(suspect,""),
         "List of Index Keys"    = convert(varchar(' + @max_keylist_size + '), keylist)
      from #indexlist
      order by owner,name,indexid'
   exec (@exec_str)
end
else
begin
   select "Name" = rtrim(owner) + "." + rtrim(name) + "." + index_name,
      c   = isnull(clust,""),
      u   = isnull(uniq,""),
      i   = isnull(ign_dup_key,""),
      a   = isnull(allow_dup,""),
      s   = isnull(suspect,""),
      "List of Index Keys"    = keylist
   from #indexlist
   order by owner,name,indexid
end

end
go

sp__monunusedindex

Ed Barlow Stored Procedures: sp__monwaits updated with formatting for SAP Sybase ASE 15 and higher

$
0
0

Ed Barlow createdSAP Sybase the sp__monwaits stored procedure for displaying the wait times since server start in Sybase ASE as part of the excellent Extended Stored Procedures by Ed Barlow (AKA the Ed Barlow Stored Procedures).

The sp__monwaits often truncated the event description making it rather difficult to determine exactly which event occurred. I’ve expanded the size the field to reflect the length of the longest event description dynamically.

 Event                                    WaitTime    Waits
 ---------------------------------------- ----------- -----------
 xact coord: pause during idle loop           4001410       66688
 wait for buffer read to complete              532248    85475068
 wait for buffer write to complete              32235    15923057
 wait for buffer validation to complete          3680      162024
 wait for mass to stop changing                 30267    10315571
 wait for mass to finish changing               10774   502746724
 wait to acquire latch                          55839     7807761
 waiting for disk write to complete            115108    40656343
 waiting for disk write to complete             60530    11697654
 waiting for disk write to complete             27566     9398819
 waiting for disk write to complete             85976    50951106
 checkpoint process idle loop                  951594       16619
 hk: pause for some time                      2713933      530621
 wait for flusher to queue full DFLPIECE       151633      150265
 wait for data from client                       1933        6000
 wait until an engine has been offlined       1000427       33342
 wait for someone else to finish reading       372601    55500541
 waiting for semaphore                         391902    13636318
 waiting for CTLIB event to complete            87265   112396697
 waiting while allocating new client sock      997833       97155
 waiting while no network read or write i    11936037  1037354467
 waiting on run queue after yield              295191    72098512
 waiting on run queue after sleep              746636 -1313156962
 replication agent sleeping in retry slee        3839          64
 replication agent sleeping during flush      1840806    12733523
 waiting for incoming network data          201256524   265587239
 waiting for network send to complete         1175318   747115161
 waiting until last chance threshold is c        1144           3
 waiting for date or time in waitfor comm       68630         210

to

 Event                                              WaitTime    Waits
 -------------------------------------------------- ----------- -----------
 waiting for incoming network data                    221594153    12452930
 waiting for client connection request                  2760845      207231
 hk: pause for some time                                2754002      443443
 xact coord: pause during idle loop                      920462       15341
 wait until an engine has been offlined                  920462       30682
 Wait until heartbeat or check interval expires          920399        1534
 checkpoint process idle loop                            919400       18224
 replication agent sleeping during flush                 777679       91871
 replication agent sleeping in retry sleep               138301        2305
 wait for flusher to queue full DFLPIECE                  31029       31055
 waiting for regular buffer read to complete              11461    37289445
 waiting for last i/o on MASS to complete                  8079     2026180
 waiting on run queue after yield                          4914     4974455
 waiting on run queue after sleep                          3652    71141496
 wait for mass read to finish when getting page            3341     5365397
 wait for i/o to finish after writing last log page        2757     3624230
 waiting for network send to complete                      1404       58634
 waiting for buf write to complete before writing          1334     1452867

Differences:

$ diff sp__monwaits.old sp__monwaits.15
1,13d0
< <
< /*
< select distinct SPID,Id=substring(Login+"("+Application+")",1,30),SecondsWaiting=sum(SecondsWaiting),"Non Network Wait Reason"=c.Description
< from master..monProcess p,master..monWaitClassInfo c, master..monWaitEventInfo i
< where p.WaitEventID = i.WaitEventID
< and   i.WaitClassID = c.WaitClassID
< and   c.Description!="waiting for input from the network"
< group by c.WaitClassID,SPID
< order by SPID
< */
<
<
22d8
<
32a19,21
> declare @max_eventstr_size varchar(4)
> declare @exec_str varchar(2000)
>
34c23,25
< select "Event"=substring(i.Description,1,40),WaitTime,Waits
---
> begin
>       select "Event" = i.Description, WaitTime, Waits
>     into #tmp_nodelay
37a29,42
>
>     if @dont_format is null
>     begin
>         select @max_eventstr_size = convert(varchar(3), isnull(max(char_length(Event)), 1)) from #tmp_nodelay
>         select @exec_str = 'select "Event" = convert(varchar(' + @max_eventstr_size + '), Event), WaitTime, Waits from #tmp_nodelay order by WaitTime desc'
>         exec (@exec_str)
>     end
>     else
>     begin
>         select * from #tmp_nodelay order by WaitTime desc
>     end
>
>     delete #tmp_nodelay
> end
40c45
< select "Event"=substring(i.Description,1,40),WaitTime,Waits,s.WaitEventID
---
>       select "Event" = i.Description, WaitTime, Waits, s.WaitEventID
51a57
>
56,63c62
< select "Time"=convert(varchar(8),getdate(),8),
<                       "Event"=i.Event,
<                       WaitTime=s.WaitTime-i.WaitTime,
<                       Waits=s.Waits-i.Waits
<               from #tmp i, master..monSysWaits s
<               where (s.WaitTime>i.WaitTime or s.Waits>i.Waits)
< and s.WaitEventID= i.WaitEventID
<               order by WaitTime desc
---
>         select @max_eventstr_size = convert(varchar(3), isnull(max(char_length(Event)), 1)) from #tmp
64a64,73
>               select @exec_str = 'select "Time" = convert(varchar(8),getdate(),8),
>                          "Event" = convert(varchar(' + @max_eventstr_size + '), rtrim(i.Event)),
>                          WaitTime = s.WaitTime-i.WaitTime,
>                          Waits = s.Waits-i.Waits
>                  from #tmp i, master..monSysWaits s
>                  where (s.WaitTime > i.WaitTime or s.Waits > i.Waits)
>                  and s.WaitEventID= i.WaitEventID
>                  order by WaitTime desc'
>         exec (@exec_str)
>
68c77
< select "Event"=substring(i.Description,1,40),WaitTime,Waits,s.WaitEventID
---
>               select "Event"=i.Description, WaitTime, Waits, s.WaitEventID
70c79
< where s.WaitEventID= i.WaitEventID
---
>               where s.WaitEventID = i.WaitEventID

Full SQL text of sp__monwaits:

use sybsystemprocs
go
/* Procedure library copyright(c) 2004 by Edward M Barlow */

IF EXISTS (SELECT * FROM sysobjects
           WHERE  name = "sp__monwaits"
           AND    type = "P")
   DROP PROC sp__monwaits
go

CREATE PROC sp__monwaits(
                @num_sec_delay int=NULL,
                @num_iter int=NULL,
                @dont_format char(1)=NULL)
AS
set nocount on
declare @delay char(8)

declare @max_eventstr_size varchar(4)
declare @exec_str varchar(2000)

if @num_sec_delay is null
begin
        select "Event" = i.Description, WaitTime, Waits
    into #tmp_nodelay
        from master..monWaitEventInfo i, master..monSysWaits s
        where s.WaitEventID= i.WaitEventID
        and     WaitTime>1000

    if @dont_format is null
    begin
        select @max_eventstr_size = convert(varchar(3), isnull(max(char_length(Event)), 1)) from #tmp_nodelay
        select @exec_str = 'select "Event" = convert(varchar(' + @max_eventstr_size + '), Event), WaitTime, Waits from #tmp_nodelay order by WaitTime desc'
        exec (@exec_str)
    end
    else
    begin
        select * from #tmp_nodelay order by WaitTime desc
    end

    delete #tmp_nodelay
end
else
begin
        select "Event" = i.Description, WaitTime, Waits, s.WaitEventID
        into #tmp
        from master..monWaitEventInfo i, master..monSysWaits s
        where s.WaitEventID= i.WaitEventID

        if @num_sec_delay<10
                select @delay="00:00:0"+convert(char(1),@num_sec_delay)
        else
                select @delay="00:00:"+convert(char(2),@num_sec_delay)

        if @num_iter is null
                select @num_iter=100

        while @num_iter>0
        begin
                waitfor delay @delay

        select @max_eventstr_size = convert(varchar(3), isnull(max(char_length(Event)), 1)) from #tmp

                select @exec_str = 'select "Time" = convert(varchar(8),getdate(),8),
                           "Event" = convert(varchar(' + @max_eventstr_size + '), rtrim(i.Event)),
                           WaitTime = s.WaitTime-i.WaitTime,
                           Waits = s.Waits-i.Waits
                   from #tmp i, master..monSysWaits s
                   where (s.WaitTime > i.WaitTime or s.Waits > i.Waits)
                   and s.WaitEventID= i.WaitEventID
                   order by WaitTime desc'
        exec (@exec_str)

                delete #tmp

                insert #tmp
                select "Event"=i.Description, WaitTime, Waits, s.WaitEventID
                from master..monWaitEventInfo i, master..monSysWaits s
                where s.WaitEventID = i.WaitEventID

                select @num_iter = @num_iter - 1
        end
end

return

go

GRANT EXECUTE ON sp__monwaits  TO public
go

sp__monwaits

Ed Barlow Stored Procedures: sp__monrunning updated with formatting for SAP Sybase ASE 15 and higher

$
0
0

Mich Talebzadeh createdSAP Sybase the sp__monrunning stored procedure for displaying the procedures that are running for more than 100 ms as part of the excellent Extended Stored Procedures by Ed Barlow (AKA the Ed Barlow Stored Procedures).

I’ve cleaned up the format output and added the dont_format option:

$ diff sp__monrunning.old sp__monrunning.15
9c9,10
< create procedure sp__monrunning
---
> create procedure sp__monrunning(
>                      @dont_format char(1)=NULL)
11,16c12,18
< ------------------------------------------------------------------------------------------------
< -- Vers|  Date  |      Who           | DA | Description
< -------+--------+--------------------+----+-----------------------------------------------------
< -- 1.0 |07/04/06|  Mich Talebzadeh   |    | Statistics on processes currently being executed
< --     |        |                    |    | with Elapsed time > 100ms
< -------+--------+--------------------+----+-----------------------------------------------------
---
> --------------------------------------------------------------------------------------------------
> -- Vers|   Date   |      Who           | DA | Description
> -------+----------+--------------------+----+-----------------------------------------------------
> -- 1.1 |11/20/2013|  Jason Froebe      |    | Cleaned up the report format, added dont_format option
> -- 1.0 |07/04/2006|  Mich Talebzadeh   |    | Statistics on processes currently being executed
> --     |          |                    |    | with Elapsed time > 100ms
> -------+--  ------+--------------------+----+-----------------------------------------------------
18,22c20,24
< declare @time datetime
<       select @time = getdate()
<       --print ""
<       --print "Stats for various procedures at %1!. Server up since %2!", @time, @@boottime
<       --print ""
---
>     declare @max_loginname_size varchar(3)
>     declare @max_procname_size varchar(3)
>     declare @max_dbname_size varchar(3)
>     declare @exec_str varchar(2000)
>
35c37
< "Name" = substring(suser_name(p.suid),1,20),
---
>               "Name" = suser_name(p.suid),
37,39c39,42
< "Procedure" = ProcName,
<               "Database" = DBNAME,
<               "Elapsed Time/ms" = TimeMs
---
>               ProcName,
>               DBNAME,
>               TimeMs
>     into #proc_report
43c46,75
< order by TimeMs asc
---
>
>     select @max_loginname_size = convert(varchar(3), isnull( max(char_length(Name)), 1)),
>         @max_procname_size = convert(varchar(3), isnull( max(char_length(ProcName)), 1)),
>         @max_dbname_size = convert(varchar(3), isnull( max(char_length(DBNAME)), 1))
>     from #proc_report
>
>     if @dont_format is null
>     begin
>         select @exec_str = 'select
>             "Name" = convert(varchar(' + @max_loginname_size + '), Name),
>                   SPID,
>                   "Procedure" = convert(varchar(' + @max_procname_size + '), ProcName),
>                   "Database" = convert(varchar(' + @max_dbname_size + '), DBNAME),
>                   "Elapsed Time/ms" = TimeMs
>         from #proc_report
>           order by TimeMs asc'
>
>         exec (@exec_str)
>     end
>     else
>     begin
>         select
>             "Name" = Name,
>                   SPID,
>                   "Procedure" = ProcName,
>                   "Database" = DBNAME,
>                   "Elapsed Time/ms" = TimeMs
>         from #proc_report
>           order by TimeMs asc
>     end

Full SQL code of sp__monrunning:

use sybsystemprocs
go

IF EXISTS (SELECT * FROM sysobjects
           WHERE  name = "sp__monrunning"
           AND    type = "P")
   DROP PROC sp__monrunning
go
create procedure sp__monrunning(
                     @dont_format char(1)=NULL)
as
--------------------------------------------------------------------------------------------------
-- Vers|   Date   |      Who           | DA | Description
-------+----------+--------------------+----+-----------------------------------------------------
-- 1.1 |11/20/2013|  Jason Froebe      |    | Cleaned up the report format, added dont_format option
-- 1.0 |07/04/2006|  Mich Talebzadeh   |    | Statistics on processes currently being executed
--     |          |                    |    | with Elapsed time > 100ms
-------+--  ------+--------------------+----+-----------------------------------------------------
begin
    declare @max_loginname_size varchar(3)
    declare @max_procname_size varchar(3)
    declare @max_dbname_size varchar(3)
    declare @exec_str varchar(2000)

        select
                SPID,
                ProcName = isnull(object_name(ProcedureID, DBID),"UNKNOWN"),
                DBNAME = isnull(db_name(DBID), "UNKNOWN"),
                TimeMs = datediff(ms, min(StartTime), max(EndTime))
                into #performance
                from master..monSysStatement m
        where db_name(DBID) != 'sybsystemprocs'
        group by SPID, DBID, ProcedureID, BatchID
        having ProcedureID != 0

        select distinct
                "Name" = suser_name(p.suid),
                SPID,
                ProcName,
                DBNAME,
                TimeMs
    into #proc_report
        from #performance t, master..sysprocesses p
        where t.SPID = p.spid
        and TimeMs >= 100

    select @max_loginname_size = convert(varchar(3), isnull( max(char_length(Name)), 1)),
        @max_procname_size = convert(varchar(3), isnull( max(char_length(ProcName)), 1)),
        @max_dbname_size = convert(varchar(3), isnull( max(char_length(DBNAME)), 1))
    from #proc_report

    if @dont_format is null
    begin
        select @exec_str = 'select
            "Name" = convert(varchar(' + @max_loginname_size + '), Name),
                    SPID,
                    "Procedure" = convert(varchar(' + @max_procname_size + '), ProcName),
                    "Database" = convert(varchar(' + @max_dbname_size + '), DBNAME),
                    "Elapsed Time/ms" = TimeMs
        from #proc_report
            order by TimeMs asc'

        exec (@exec_str)
    end
    else
    begin
        select
            "Name" = Name,
                    SPID,
                    "Procedure" = ProcName,
                    "Database" = DBNAME,
                    "Elapsed Time/ms" = TimeMs
        from #proc_report
            order by TimeMs asc
    end
end
go
grant exec on sp__monrunning to public
go
exit

sp__monrunning

Ed Barlow Stored Procedures: sp__monobj Updated with formatting for SAP Sybase ASE 15 and higher

$
0
0

Ed Barlow createdSAP Sybase the sp__monobj uses a heuristic algorithm to find which objects are most busy as part of the excellent Extended Stored Procedures by Ed Barlow (AKA the Ed Barlow Stored Procedures).

I’ve cleaned up the format output

Differences:

diff sp__monobj.old sp__monobj.15
17a18,26
> --------------------------------------------------------------------------------------------------
> -- Vers|   Date   |      Who           | DA | Description
> -------+----------+--------------------+----+-----------------------------------------------------
> -- 1.1 |11/20/2013|  Jason Froebe      |    | Fix formatting of outputs
> -- 1.0 |  2006    |  Edward Barlow     |    | Shows Highest Usage Objects Based On Mda tables.
> --     |          |                    |    |  This uses a heuristic algorithm to find what objects
> --     |          |                    |    |  are most busy.
> -------+----------+--------------------+----+-----------------------------------------------------
>
21a31,34
> declare @max_objectname_size varchar(3)
> declare @exec_str varchar(2000)
>
>
34a48,51
>     print ""
>     print "    score = LogicalReads/100 + PhysicalReads/10 + PhysicalWrites + RowsInserted + RowsDeleted + RowsUpdated + LockRequests + Lockwaits"
>     print ""
>
36,37c53,55
< select ObjName=convert(varchar(40),db_name(DBID)+"."+object_name(ObjectID,DBID)),
<       score= LogicalReads/100 +
---
>
>       select ObjName = db_name(DBID) + ".." + object_name(ObjectID, DBID),
>       score = LogicalReads/100        +
45,46c63,65
< from    master..monOpenObjectActivity
<       where   IndexID=0
---
>     into #busy_report
>       from master..monOpenObjectActivity
>       where IndexID=0
55c74
< and     db_name(DBID)!="tempdb"
---
>       and     DBName !="tempdb"
57a77
>
58a79,87
>
>     select @max_objectname_size = convert(varchar(3), isnull( max(char_length(ObjName)), 1)) from #busy_report
>
>     select @exec_str = 'select "Object Name" = convert(varchar(' + @max_objectname_size + '), ObjName), score
>         from #busy_report
>         order by score desc'
>
>     exec (@exec_str)
>
72a102,121
>     create table #busy_report_iter_obj (
>         ObjName varchar(255) not null,
>         Op bigint not null,
>         LogReads int not null,
>         PhysReads int not null,
>         PageReads int not null,
>         Writes int not null,
>         Ins int not null,
>         Del int not null,
>         Upd int not null,
>         Locks int not null,
>         LockWt int not null)
>
>     create table #busy_report_iter (
>         ObjName varchar(255) not null,
>         Op int not null,
>         Reads int not null,
>         Writes int not null,
>         NumRows bigint not null)
>
81,86c130,131
< -- select *
<                       -- from master..monOpenObjectActivity
<                       -- where IndexID=0 and db_name(DBID)!='tempdb'
<                       -- and ( @object_name is null or @object_name=object_name(ObjectID, DBID))
<
<               select distinct ObjName=convert(varchar(39),db_name(o.DBID)+"."+object_name(o.ObjectID,o.DBID)),
---
>             insert into #busy_report_iter_obj
>                   select distinct ObjName = db_name(o.DBID) + ".." + object_name(o.ObjectID,o.DBID),
88c133
< LogReads=o.LogicalReads - i.LogicalReads,
---
>                           LogReads=o.LogicalReads - i.LogicalReads,
92,103c137,167
< "Ins"=o.RowsInserted -i.RowsInserted,
<                               "Del"= o.RowsDeleted  - i.RowsDeleted,
<                               "Upd"= o.RowsUpdated - i.RowsUpdated ,
<                               "Locks"= o.LockRequests - i.LockRequests,
<                               "LockWt"= o.LockWaits - i.LockWaits
<               from  master..monOpenObjectActivity o,#tmp i
<               where o.IndexID=i.IndexID
<                       and o.ObjectID=i.ObjectID
<                       and o.DBID=i.DBID
<                       and o.IndexID=i.IndexID
<                       and o.IndexID=0
<                       and i.IndexID=0
---
>                           Ins=o.RowsInserted -i.RowsInserted,
>                               Del= o.RowsDeleted  - i.RowsDeleted,
>                               Upd= o.RowsUpdated - i.RowsUpdated ,
>                               Locks= o.LockRequests - i.LockRequests,
>                               LockWt= o.LockWaits - i.LockWaits
>                   from  master..monOpenObjectActivity o,#tmp i
>                   where o.IndexID=i.IndexID
>                           and o.ObjectID=i.ObjectID
>                           and o.DBID=i.DBID
>                           and o.IndexID=i.IndexID
>                           and o.IndexID=0
>                           and i.IndexID=0
>
>             select @max_objectname_size = convert(varchar(3), isnull( max(char_length(ObjName)), 1)) from #busy_report_iter_obj
>
>             select @exec_str = 'select "Object Name" = convert(varchar(' + @max_objectname_size + '), ObjName),
>                               Op,
>                           LogReads,
>                               PhysReads,
>                               PageReads,
>                               Writes,
>                           Ins,
>                               Del,
>                               Upd,
>                               Locks,
>                               LockWt
>                 from #busy_report_iter_obj'
>
>             exec (@exec_str)
>
>             delete #busy_report_iter_obj
107c171
< set rowcount 10
---
>                   set rowcount 10
109,138c173,202
< select distinct ObjName=convert(varchar(39),db_name(o.DBID)+"."+object_name(o.ObjectID,o.DBID)),
<               Op=o.Operations-i.Operations,
<       Reads=o.LogicalReads+ o.PhysicalReads- i.LogicalReads- i.PhysicalReads,
<               Writes=o.PhysicalWrites-i.PhysicalWrites,
<       "Rows"=o.RowsInserted + o.RowsDeleted   + o.RowsUpdated-i.RowsInserted - i.RowsDeleted - i.RowsUpdated
<       from  master..monOpenObjectActivity o,#tmp i
<    where    o.IndexID=i.IndexID
<               and o.ObjectID=i.ObjectID
<               and o.DBID=i.DBID
<               and o.IndexID=i.IndexID
<               and o.IndexID=0
<               and i.IndexID=0
<               -- and ( o.LogicalReads>0 or o.LockRequests>0 )
< order by
<       o.LogicalReads/100      +
<       o.PhysicalReads/10      +
<       o.PhysicalWrites                +
<       o.RowsInserted                  +
<       o.RowsDeleted                   +
<       o.RowsUpdated                   +
<       o.LockRequests/100   +
<       o.LockWaits             -
<       i.LogicalReads/100      -
<       i.PhysicalReads/10      -
<       i.PhysicalWrites                -
<       i.RowsInserted                  -
<       i.RowsDeleted                   -
<       i.RowsUpdated                   -
<       i.LockRequests/100   -
<       i.LockWaits    desc
---
>             insert into #busy_report_iter
>             select distinct ObjName = db_name(o.DBID) + ".." + object_name(o.ObjectID,o.DBID),
>                       Op = o.Operations-i.Operations,
>                 Reads = o.LogicalReads+ o.PhysicalReads- i.LogicalReads- i.PhysicalReads,
>                       Writes = o.PhysicalWrites-i.PhysicalWrites,
>                 NumRows = o.RowsInserted + o.RowsDeleted   + o.RowsUpdated-i.RowsInserted - i.RowsDeleted - i.RowsUpdated
>             from  master..monOpenObjectActivity o,#tmp i
>             where    o.IndexID=i.IndexID
>                       and o.ObjectID=i.ObjectID
>                       and o.DBID=i.DBID
>                       and o.IndexID=i.IndexID
>                       and o.IndexID=0
>                       and i.IndexID=0
>             order by
>                   o.LogicalReads/100  +
>                 o.PhysicalReads/10    +
>                 o.PhysicalWrites              +
>                 o.RowsInserted                +
>                 o.RowsDeleted                 +
>                 o.RowsUpdated                 +
>                 o.LockRequests/100   +
>                 o.LockWaits                   -
>                   i.LogicalReads/100  -
>                 i.PhysicalReads/10    -
>                 i.PhysicalWrites              -
>                 i.RowsInserted                -
>                 i.RowsDeleted                 -
>                 i.RowsUpdated                 -
>                 i.LockRequests/100   -
>                 i.LockWaits    desc
139a204,215
>             select @max_objectname_size = convert(varchar(3), isnull( max(char_length(ObjName)), 1)) from #busy_report_iter
>
>             select @exec_str = 'select "Object Name" = convert(varchar(' + @max_objectname_size + '), ObjName),
>                 Op,
>                 Reads,
>                 Writes,
>                 NumRows
>             from #busy_report_iter'
>
>             exec (@exec_str)
>
>             delete #busy_report_iter
152d227
< -- select 1,* from #tmp where object_id('sp_aux_getsize')=ObjectID and DBID=db_id('master')

SQL of sp__monobj:

use sybsystemprocs
go
/* Procedure library copyright(c) 2004-2006 by Edward M Barlow */

IF EXISTS (SELECT * FROM sysobjects
           WHERE  name = "sp__monobj"
           AND    type = "P")
   DROP PROC sp__monobj

go

CREATE PROC sp__monobj(
                @num_sec_delay int=NULL,
                @num_iter int=NULL,
                @dont_format char(1)=NULL,
                @object_name varchar(30)=NULL)
AS
--------------------------------------------------------------------------------------------------
-- Vers|   Date   |      Who           | DA | Description
-------+----------+--------------------+----+-----------------------------------------------------
-- 1.1 |11/20/2013|  Jason Froebe      |    | Fix formatting of outputs
-- 1.0 |  2006    |  Edward Barlow     |    | Shows Highest Usage Objects Based On Mda tables.
--     |          |                    |    |  This uses a heuristic algorithm to find what objects
--     |          |                    |    |  are most busy.
-------+----------+--------------------+----+-----------------------------------------------------

set nocount on
declare @delay char(8)
declare @objid int

declare @max_objectname_size varchar(3)
declare @exec_str varchar(2000)


if @object_name is not null
begin
        select @objid=ObjectID
        from master..monOpenObjectActivity where object_name(ObjectID,DBID)=@object_name
        if @objid is null
                return
end


if @num_sec_delay is null
begin
        --Busy Object Report
        print "Top 20 Used Objects"
    print ""
    print "    score = LogicalReads/100 + PhysicalReads/10 + PhysicalWrites + RowsInserted + RowsDeleted + RowsUpdated + LockRequests + Lockwaits"
    print ""

        set rowcount 20

        select ObjName = db_name(DBID) + ".." + object_name(ObjectID, DBID),
        score = LogicalReads/100        +
                PhysicalReads/10 +
                PhysicalWrites +
                RowsInserted   +
                RowsDeleted    +
                RowsUpdated    +
                LockRequests   +
                LockWaits
    into #busy_report
        from master..monOpenObjectActivity
        where IndexID=0
        and LogicalReads/100    +
                PhysicalReads/10 +
                PhysicalWrites +
                RowsInserted   +
                RowsDeleted    +
                RowsUpdated    +
                LockRequests   +
                LockWaits      >1000
        and     DBName !="tempdb"
        and ( @object_name is null or @object_name=object_name(ObjectID, DBID))
        order by score desc

        set rowcount 0

    select @max_objectname_size = convert(varchar(3), isnull( max(char_length(ObjName)), 1)) from #busy_report

    select @exec_str = 'select "Object Name" = convert(varchar(' + @max_objectname_size + '), ObjName), score
        from #busy_report
        order by score desc'

    exec (@exec_str)

end
else
begin
        select *
        into #tmp
        from master..monOpenObjectActivity
        where IndexID=0 and db_name(DBID)!='tempdb'
        and ( @object_name is null or ObjectID=@objid )

        if @num_sec_delay<10
                select @delay="00:00:0"+convert(char(1),@num_sec_delay)
        else
                select @delay="00:00:"+convert(char(2),@num_sec_delay)

    create table #busy_report_iter_obj (
        ObjName varchar(255) not null,
        Op bigint not null,
        LogReads int not null,
        PhysReads int not null,
        PageReads int not null,
        Writes int not null,
        Ins int not null,
        Del int not null,
        Upd int not null,
        Locks int not null,
        LockWt int not null)

    create table #busy_report_iter (
        ObjName varchar(255) not null,
        Op int not null,
        Reads int not null,
        Writes int not null,
        NumRows bigint not null)

        if @num_iter is null
                select @num_iter=100
        while @num_iter>0
        begin
                waitfor delay @delay

                if( @object_name is not null )
                begin
            insert into #busy_report_iter_obj
                    select distinct ObjName = db_name(o.DBID) + ".." + object_name(o.ObjectID,o.DBID),
                                Op=o.Operations-i.Operations,
                    LogReads=o.LogicalReads - i.LogicalReads,
                                PhysReads=o.PhysicalReads- i.PhysicalReads,
                                PageReads=o.PagesRead- i.PagesRead,
                                Writes=o.PhysicalWrites-i.PhysicalWrites,
                    Ins=o.RowsInserted -i.RowsInserted,
                                Del= o.RowsDeleted  - i.RowsDeleted,
                                Upd= o.RowsUpdated - i.RowsUpdated ,
                                Locks= o.LockRequests - i.LockRequests,
                                LockWt= o.LockWaits - i.LockWaits
            from  master..monOpenObjectActivity o,#tmp i
                    where o.IndexID=i.IndexID
                            and o.ObjectID=i.ObjectID
                            and o.DBID=i.DBID
                            and o.IndexID=i.IndexID
                            and o.IndexID=0
                            and i.IndexID=0

            select @max_objectname_size = convert(varchar(3), isnull( max(char_length(ObjName)), 1)) from #busy_report_iter_obj

            select @exec_str = 'select "Object Name" = convert(varchar(' + @max_objectname_size + '), ObjName),
                                Op,
                    LogReads,
                                PhysReads,
                                PageReads,
                                Writes,
                    Ins,
                                Del,
                                Upd,
                                Locks,
                                LockWt
                from #busy_report_iter_obj'

            exec (@exec_str)

            delete #busy_report_iter_obj
                end
                else
                begin
                    set rowcount 10

            insert into #busy_report_iter
            select distinct ObjName = db_name(o.DBID) + ".." + object_name(o.ObjectID,o.DBID),
                        Op = o.Operations-i.Operations,
                Reads = o.LogicalReads+ o.PhysicalReads- i.LogicalReads- i.PhysicalReads,
                        Writes = o.PhysicalWrites-i.PhysicalWrites,
                NumRows = o.RowsInserted + o.RowsDeleted   + o.RowsUpdated-i.RowsInserted - i.RowsDeleted - i.RowsUpdated
            from  master..monOpenObjectActivity o,#tmp i
            where    o.IndexID=i.IndexID
                        and o.ObjectID=i.ObjectID
                        and o.DBID=i.DBID
                        and o.IndexID=i.IndexID
                        and o.IndexID=0
                        and i.IndexID=0
            order by
                    o.LogicalReads/100  +
                o.PhysicalReads/10      +
                o.PhysicalWrites                +
                o.RowsInserted                  +
                o.RowsDeleted                   +
                o.RowsUpdated                   +
                o.LockRequests/100   +
                o.LockWaits             -
                    i.LogicalReads/100  -
                i.PhysicalReads/10      -
                i.PhysicalWrites                -
                i.RowsInserted                  -
                i.RowsDeleted                   -
                i.RowsUpdated                   -
                i.LockRequests/100   -
                i.LockWaits    desc

            select @max_objectname_size = convert(varchar(3), isnull( max(char_length(ObjName)), 1)) from #busy_report_iter

            select @exec_str = 'select "Object Name" = convert(varchar(' + @max_objectname_size + '), ObjName),
                Op,
                Reads,
                Writes,
                NumRows
            from #busy_report_iter'

            exec (@exec_str)

            delete #busy_report_iter
                set rowcount 0

                end

                delete #tmp

                insert #tmp
                select *
                from master..monOpenObjectActivity
                where IndexID=0 and db_name(DBID)!='tempdb'
                and ( @object_name is null or ObjectID=@objid )

                select @num_iter = @num_iter - 1
        end
end

return

go

GRANT EXECUTE ON sp__monobj  TO public
go

sp__monwaits

HOWTO: Building Perl Module DBD::Sybase 1.15 for ActiveState Perl (Windows 32bit) 5.16.3 using the MinGW compiler

$
0
0

We no longer are tied to using Microsoft’s SAP SybaseVisual C++ compiler for building Michael Peppler’s Perl Module DBD::Sybase 1.15 for ActiveState Perl (Windows 32bit)!

We need to make a few changes to SAP Sybase’s Openclient though. Don’t worry, the changes are only needed to build the module. I used Sybase Openclient 15.7 ESD 7 but you should be able to use any 15.7 version of Openclient with minimal changes.

%SYBASE%\%SYBASE_OCS%\include\csconfig.h differences:

$ diff csconfig.h.old csconfig.h
58a59,63
> /* Load MinGW specific definitions */
> #if defined(__MINGW32__)
> #include "_mingw.h"
> #endif /* __MINGW32__ */
>
74c79
< #if ((SYB_MSC_VER >= 800)  || defined(__BORLANDC__))
---
> #if ((SYB_MSC_VER >= 800)  || defined(__BORLANDC__)) || defined(__MINGW32__)
84c89
< #else /* ((SYB_MSC_VER >= 800) || defined(__BORLANDC__)) */
---
> #else /* ((SYB_MSC_VER >= 800) || defined(__BORLANDC__)) || defined(__MINGW32__) */
94c99
< #endif /* ((SYB_MSC_VER >= 800) || defined(__BORLANDC__)) */
---
> #endif /* ((SYB_MSC_VER >= 800) || defined(__BORLANDC__)) || defined(__MINGW32__) */

%SYBASE%\%SYBASE_OCS%\include\sybfront.h differences:

$ diff sybfront.h.old sybfront.h
162c162
< #if !defined(_MSC_VER) && !defined(__BORLANDC__)
---
> #if !defined(_MSC_VER) && !defined(__BORLANDC__) && !defined(__MINGW32__)
180c180
< #if !defined(_MSC_VER) && !defined(__BORLANDC__)
---
> #if !defined(_MSC_VER) && !defined(__BORLANDC__) && !defined(__MINGW32__)

csconfig
sybfront

We now need to copy the *.lib files in %SYBASE%\%SYBASE_OCS%\lib appending “.a” in place of the “.lib” suffix:
libs

Don’t you perlthink SAP Sybase should add the changes above to OpenClient? I think so. Let your SAP Representative know!

Now we’re ready to build the module!

U:\build\DBD-Sybase-1.15>perl Makefile.PL
Set up gcc environment - 3.4.5 (mingw-vista special r3)
Sybase OpenClient 15.7 found.

By default DBD::Sybase 1.05 and later use the 'CHAINED' mode (where available)
when 'AutoCommit' is turned off. Versions 1.04 and older instead managed
the transactions explicitly with a 'BEGIN TRAN' before the first DML
statement. Using the 'CHAINED' mode is preferable as it is the way that
Sybase implements AutoCommit handling for both its ODBC and JDBC drivers.

Use 'CHAINED' mode by default (Y/N) [Y]:

The DBD::Sybase module need access to a Sybase server to run the tests.
To clear an entry please enter 'undef'
Sybase server to use (default: SYBASE): test_svr
User ID to log in to Sybase (default: sa):
Password (default: undef):
Sybase database to use on sd02 (default: undef): tempdb

* Writing login information, including password, to file PWD.

Checking if your kit is complete...
Looks good
Warning (mostly harmless): No library found for -llibsybtcl.lib
Warning (mostly harmless): No library found for -llibsybcomn.lib
Warning (mostly harmless): No library found for -llibsybintl.lib
Multiple copies of Driver.xst found in: C:/Perl/site/lib/auto/DBI/ C:/Perl/lib/auto/DBI/ at Makefile.PL line 80.
Using DBI 1.63 (for perl 5.016003 on MSWin32-x86-multi-thread) installed in C:/Perl/site/lib/auto/DBI/
Generating a dmake-style Makefile
Writing Makefile for DBD::Sybase
Writing MYMETA.yml and MYMETA.json

So far so good, so let’s continue with compiling and building the module:

U:\build\DBD-Sybase-1.15>dmake
dmake.exe:  makefile:  line 454:  Warning: -- Macro `BOOTSTRAP' redefined after use
cp dbd-sybase.pod blib\lib\DBD\dbd-sybase.pod
cp Sybase.pm blib\lib\DBD\Sybase.pm
C:\Perl\bin\perl.exe -p -e "s/~DRIVER~/Sybase/g" C:\Perl\site\lib\auto\DBI\Driver.xst > Sybase.xsi
C:\Perl\bin\perl.exe C:\Perl\site\lib\ExtUtils\xsubpp  -typemap C:\Perl\lib\ExtUtils\typemap  Sybase.xs > Sybase.xsc && C:\Perl\bin\perl.exe -MExtUtil
s::Command -e mv -- Sybase.xsc Sybase.c
C:\Perl\site\bin\gcc.exe -c  -IC:\Sybase/OCS-15_0/include -IC:/Perl/site/lib/auto/DBI   -DNDEBUG -DWIN32 -D_CONSOLE -DNO_STRICT -DPERL_TEXTMODE_SCRIPT
S -DUSE_SITECUSTOMIZE -DPERL_IMPLICIT_CONTEXT -DPERL_IMPLICIT_SYS -DUSE_PERLIO -D_USE_32BIT_TIME_T -DHASATTRIBUTE -fno-strict-aliasing -mms-bitfields
-O2       -DVERSION=\"1.15\"    -DXS_VERSION=\"1.15\"  "-IC:\Perl\lib\CORE"   Sybase.c
C:\Perl\site\bin\gcc.exe -c  -IC:\Sybase/OCS-15_0/include -IC:/Perl/site/lib/auto/DBI   -DNDEBUG -DWIN32 -D_CONSOLE -DNO_STRICT -DPERL_TEXTMODE_SCRIPT
S -DUSE_SITECUSTOMIZE -DPERL_IMPLICIT_CONTEXT -DPERL_IMPLICIT_SYS -DUSE_PERLIO -D_USE_32BIT_TIME_T -DHASATTRIBUTE -fno-strict-aliasing -mms-bitfields
-O2       -DVERSION=\"1.15\"    -DXS_VERSION=\"1.15\"  "-IC:\Perl\lib\CORE"   dbdimp.c
dbdimp.c: In function `syb_st_execute':
dbdimp.c:3906: warning: passing arg 2 of `ct_results' from incompatible pointer type
dbdimp.c:3930: warning: passing arg 5 of `ct_bind' from incompatible pointer type
Running Mkbootstrap for DBD::Sybase ()
C:\Perl\bin\perl.exe -MExtUtils::Command -e chmod -- 644 Sybase.bs
C:\Perl\bin\perl.exe -MExtUtils::Mksymlists \
     -e "Mksymlists('NAME'=>\"DBD::Sybase\", 'DLBASE' => 'Sybase', 'DL_FUNCS' => {  }, 'FUNCLIST' => [], 'IMPORTS' => {  }, 'DL_VARS' => []);"
Set up gcc environment - 3.4.5 (mingw-vista special r3)
C:\Perl\site\bin\dlltool.exe --def Sybase.def --output-exp dll.exp
C:\Perl\site\bin\g++.exe -o blib\arch\auto\DBD\Sybase\Sybase.dll -Wl,--base-file -Wl,dll.base -LC:\Sybase/OCS-15_0/lib -mdll -L"C:\Perl\lib\CORE" Syba
se.o    dbdimp.o   C:\Perl\lib\CORE\perl516.lib C:\Sybase\OCS-15_0\lib\libsybct.lib C:\Sybase\OCS-15_0\lib\libsybcs.lib C:\Sybase\OCS-15_0\lib\libsybb
lk.lib C:\Perl\site\lib\auto\MinGW\lib\libm.a C:\Perl\site\lib\auto\MinGW\lib\libkernel32.a C:\Perl\site\lib\auto\MinGW\lib\libuser32.a C:\Perl\site\l
ib\auto\MinGW\lib\libgdi32.a C:\Perl\site\lib\auto\MinGW\lib\libwinspool.a C:\Perl\site\lib\auto\MinGW\lib\libcomdlg32.a C:\Perl\site\lib\auto\MinGW\l
ib\libadvapi32.a C:\Perl\site\lib\auto\MinGW\lib\libshell32.a C:\Perl\site\lib\auto\MinGW\lib\libole32.a C:\Perl\site\lib\auto\MinGW\lib\liboleaut32.a
 C:\Perl\site\lib\auto\MinGW\lib\libnetapi32.a C:\Perl\site\lib\auto\MinGW\lib\libuuid.a C:\Perl\site\lib\auto\MinGW\lib\libws2_32.a C:\Perl\site\lib\
auto\MinGW\lib\libmpr.a C:\Perl\site\lib\auto\MinGW\lib\libwinmm.a C:\Perl\site\lib\auto\MinGW\lib\libversion.a C:\Perl\site\lib\auto\MinGW\lib\libodb
c32.a C:\Perl\site\lib\auto\MinGW\lib\libodbccp32.a C:\Perl\site\lib\auto\MinGW\lib\libcomctl32.a C:\Perl\site\lib\auto\MinGW\lib\libmsvcrt.a dll.exp
C:\Perl\site\bin\dlltool.exe --def Sybase.def --base-file dll.base --output-exp dll.exp
C:\Perl\site\bin\g++.exe -o blib\arch\auto\DBD\Sybase\Sybase.dll -LC:\Sybase/OCS-15_0/lib -mdll -L"C:\Perl\lib\CORE" Sybase.o   dbdimp.o   C:\Perl\lib
\CORE\perl516.lib C:\Sybase\OCS-15_0\lib\libsybct.lib C:\Sybase\OCS-15_0\lib\libsybcs.lib C:\Sybase\OCS-15_0\lib\libsybblk.lib C:\Perl\site\lib\auto\M
inGW\lib\libm.a C:\Perl\site\lib\auto\MinGW\lib\libkernel32.a C:\Perl\site\lib\auto\MinGW\lib\libuser32.a C:\Perl\site\lib\auto\MinGW\lib\libgdi32.a C
:\Perl\site\lib\auto\MinGW\lib\libwinspool.a C:\Perl\site\lib\auto\MinGW\lib\libcomdlg32.a C:\Perl\site\lib\auto\MinGW\lib\libadvapi32.a C:\Perl\site\
lib\auto\MinGW\lib\libshell32.a C:\Perl\site\lib\auto\MinGW\lib\libole32.a C:\Perl\site\lib\auto\MinGW\lib\liboleaut32.a C:\Perl\site\lib\auto\MinGW\l
ib\libnetapi32.a C:\Perl\site\lib\auto\MinGW\lib\libuuid.a C:\Perl\site\lib\auto\MinGW\lib\libws2_32.a C:\Perl\site\lib\auto\MinGW\lib\libmpr.a C:\Per
l\site\lib\auto\MinGW\lib\libwinmm.a C:\Perl\site\lib\auto\MinGW\lib\libversion.a C:\Perl\site\lib\auto\MinGW\lib\libodbc32.a C:\Perl\site\lib\auto\Mi
nGW\lib\libodbccp32.a C:\Perl\site\lib\auto\MinGW\lib\libcomctl32.a C:\Perl\site\lib\auto\MinGW\lib\libmsvcrt.a dll.exp
C:\Perl\bin\perl.exe -MExtUtils::Command -e chmod -- 755 blib\arch\auto\DBD\Sybase\Sybase.dll

Now, you might be thinking that since it compiled it should be good huh? Nah, we test things here! ;-)

U:\build\DBD-Sybase-1.15>dmake test
dmake.exe:  makefile:  line 454:  Warning: -- Macro `BOOTSTRAP' redefined after use
C:\Perl\bin\perl.exe "-MExtUtils::Command::MM" "-MTest::Harness" "-e" "undef *Test::Harness::Switches; test_harness(0, 'blib\lib', 'blib\arch')" t/*.t

t/autocommit.t .. ok
t/base.t ........ ok
t/exec.t ........ ok
t/fail.t ........ ok
t/login.t ....... 1/6 DBD::Sybase::db ping failed: ct_cmd_alloc failed at t/login.t line 32.
t/login.t ....... ok
t/main.t ........ ok
t/multi_sth.t ... ok
t/nsql.t ........ ok
t/place.t ....... ok
t/thread.t ...... skipped: this DBD::Sybase not configured to support iThreads
t/utf8.t ........ ok
t/xblk.t ........ ok
t/xblob.t ....... ok
All tests successful.
Files=13, Tests=242, 17 wallclock secs ( 0.16 usr +  0.22 sys =  0.37 CPU)
Result: PASS

No major issues so we’re ready to build ActiveState’s PPD file and get it ready distribute:

U:\build\DBD-Sybase-1.15>dmake ppd
dmake.exe:  makefile:  line 454:  Warning: -- Macro `BOOTSTRAP' redefined after use

Zip the blib directory and name it “DBD-Sybase-1.15.zip”. Create a new directory named “MSWin32-x86-multi-thread-5.16″ and copy the zip file into it.

You need to tell PPM where to find the zip file. The PPD file is simply an XML document, so we can just update the codebase:

<softpkg NAME="DBD-Sybase" VERSION="1.15">
    <abstract>DBI driver for Sybase datasources</abstract>
    <author>Michael Peppler (mpeppler@peppler.org)</author>
    <implementation>
        <architecture NAME="MSWin32-x86-multi-thread-5.16"></architecture>
        <codebase HREF="MSWin32-x86-multi-thread-5.16\DBD-Sybase-1.15.zip"></codebase>
    </implementation>
</softpkg>

Let’s test that it actually installs using ActiveState’s PPM:

U:\build\DBD-Sybase-1.15>ppm install DBD-Sybase.ppd
Unpacking DBD-Sybase-1.15...done
Generating HTML for DBD-Sybase-1.15...done
Updating files in site area...done
   5 files installed

U:\build\DBD-Sybase-1.15>

We only need to zip up the PPD and the MSWin32-x86-multi-thread-5.16 directory listed in the PPD. It is now ready to distribute. How you do it is entirely up to you.
DBD-Sybase-1.15 for ActiveState Perl 5.16 Win32

For ActiveState Perl 64bit, you will need to use Microsoft Visual Studio. However, since the support of 64bit Perl on Windows by ActiveState is rather poor, I would recommend using the 32bit version instead.

Viewing all 102 articles
Browse latest View live